blob: 535a9f6015d8e153f3ccb79335664bcf6acbfb22 [file] [log] [blame]
//===-- CxxStringTypes.cpp ------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CxxStringTypes.h"
#include "llvm/Support/ConvertUTF.h"
#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/DataFormatters/FormattersHelpers.h"
#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/TypeSummary.h"
#include "lldb/Host/Time.h"
#include "lldb/Target/ProcessStructReader.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/Stream.h"
#include <algorithm>
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
using StringElementType = StringPrinter::StringElementType;
static constexpr std::pair<const char *, Format>
getElementTraits(StringElementType ElemType) {
switch (ElemType) {
case StringElementType::UTF8:
return std::make_pair("u8", lldb::eFormatUnicode8);
case StringElementType::UTF16:
return std::make_pair("u", lldb::eFormatUnicode16);
case StringElementType::UTF32:
return std::make_pair("U", lldb::eFormatUnicode32);
default:
return std::make_pair(nullptr, lldb::eFormatInvalid);
}
}
template <StringElementType ElemType>
static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) {
Address valobj_addr = GetArrayAddressOrPointerValue(valobj);
if (!valobj_addr.IsValid())
return false;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
options.SetTargetSP(valobj.GetTargetSP());
options.SetStream(&stream);
options.SetPrefixToken(getElementTraits(ElemType).first);
if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options))
stream.Printf("Summary Unavailable");
return true;
}
template <StringElementType ElemType>
static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) {
DataExtractor data;
Status error;
valobj.GetData(data, error);
if (error.Fail())
return false;
std::string value;
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
constexpr auto ElemTraits = getElementTraits(ElemType);
valobj.GetValueAsCString(ElemTraits.second, value);
if (!value.empty())
stream.Printf("%s ", value.c_str());
options.SetData(std::move(data));
options.SetStream(&stream);
options.SetPrefixToken(ElemTraits.first);
options.SetQuote('\'');
options.SetSourceSize(1);
options.SetBinaryZeroIsTerminator(false);
return StringPrinter::ReadBufferAndDumpToStream<ElemType>(options);
}
bool lldb_private::formatters::Char8StringSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream);
}
bool lldb_private::formatters::Char16StringSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream);
}
bool lldb_private::formatters::Char32StringSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream);
}
bool lldb_private::formatters::WCharStringSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
Address valobj_addr = GetArrayAddressOrPointerValue(valobj);
if (!valobj_addr.IsValid())
return false;
// Get a wchar_t basic type from the current type system
CompilerType wchar_compiler_type =
valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
if (!wchar_compiler_type)
return false;
// Safe to pass nullptr for exe_scope here.
llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
if (!size)
return false;
const uint32_t wchar_size = *size;
StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
options.SetLocation(valobj_addr);
options.SetTargetSP(valobj.GetTargetSP());
options.SetStream(&stream);
options.SetPrefixToken("L");
switch (wchar_size) {
case 8:
return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8>(
options);
case 16:
return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF16>(
options);
case 32:
return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF32>(
options);
default:
stream.Printf("size for wchar_t is not valid");
return true;
}
return true;
}
bool lldb_private::formatters::Char8SummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharSummaryProvider<StringElementType::UTF8>(valobj, stream);
}
bool lldb_private::formatters::Char16SummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharSummaryProvider<StringElementType::UTF16>(valobj, stream);
}
bool lldb_private::formatters::Char32SummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
return CharSummaryProvider<StringElementType::UTF32>(valobj, stream);
}
bool lldb_private::formatters::WCharSummaryProvider(
ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
DataExtractor data;
Status error;
valobj.GetData(data, error);
if (error.Fail())
return false;
// Get a wchar_t basic type from the current type system
CompilerType wchar_compiler_type =
valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
if (!wchar_compiler_type)
return false;
// Safe to pass nullptr for exe_scope here.
llvm::Optional<uint64_t> size = wchar_compiler_type.GetBitSize(nullptr);
if (!size)
return false;
const uint32_t wchar_size = *size;
StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
options.SetData(std::move(data));
options.SetStream(&stream);
options.SetPrefixToken("L");
options.SetQuote('\'');
options.SetSourceSize(1);
options.SetBinaryZeroIsTerminator(false);
switch (wchar_size) {
case 8:
return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF8>(
options);
case 16:
return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF16>(
options);
case 32:
return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF32>(
options);
default:
stream.Printf("size for wchar_t is not valid");
return true;
}
return true;
}