1//===-- CxxStringTypes.cpp ------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "CxxStringTypes.h"
10
11#include "llvm/Support/ConvertUTF.h"
12
13#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
14#include "lldb/DataFormatters/FormattersHelpers.h"
15#include "lldb/DataFormatters/StringPrinter.h"
16#include "lldb/DataFormatters/TypeSummary.h"
17#include "lldb/Host/Time.h"
18#include "lldb/Target/SectionLoadList.h"
19#include "lldb/Target/Target.h"
20#include "lldb/Target/Thread.h"
21#include "lldb/Utility/DataBufferHeap.h"
22#include "lldb/Utility/Endian.h"
23#include "lldb/Utility/Status.h"
24#include "lldb/Utility/Stream.h"
25#include "lldb/ValueObject/ValueObject.h"
26#include "lldb/ValueObject/ValueObjectConstResult.h"
27
28#include <algorithm>
29#include <optional>
30
31using namespace lldb;
32using namespace lldb_private;
33using namespace lldb_private::formatters;
34
35using StringElementType = StringPrinter::StringElementType;
36
37static constexpr std::pair<const char *, Format>
38getElementTraits(StringElementType ElemType) {
39 switch (ElemType) {
40 case StringElementType::UTF8:
41 return std::make_pair(x: "u8", y: lldb::eFormatUnicode8);
42 case StringElementType::UTF16:
43 return std::make_pair(x: "u", y: lldb::eFormatUnicode16);
44 case StringElementType::UTF32:
45 return std::make_pair(x: "U", y: lldb::eFormatUnicode32);
46 default:
47 return std::make_pair(x: nullptr, y: lldb::eFormatInvalid);
48 }
49}
50
51template <StringElementType ElemType>
52static bool CharStringSummaryProvider(ValueObject &valobj, Stream &stream) {
53 Address valobj_addr = GetArrayAddressOrPointerValue(valobj);
54 if (!valobj_addr.IsValid())
55 return false;
56
57 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
58 options.SetLocation(valobj_addr);
59 options.SetTargetSP(valobj.GetTargetSP());
60 options.SetStream(&stream);
61 options.SetPrefixToken(getElementTraits(ElemType).first);
62
63 if (!StringPrinter::ReadStringAndDumpToStream<ElemType>(options))
64 stream.Printf(format: "Summary Unavailable");
65
66 return true;
67}
68
69template <StringElementType ElemType>
70static bool CharSummaryProvider(ValueObject &valobj, Stream &stream) {
71 DataExtractor data;
72 Status error;
73 valobj.GetData(data, error);
74
75 if (error.Fail())
76 return false;
77
78 std::string value;
79 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
80
81 constexpr auto ElemTraits = getElementTraits(ElemType);
82 valobj.GetValueAsCString(format: ElemTraits.second, destination&: value);
83
84 if (!value.empty())
85 stream.Printf(format: "%s ", value.c_str());
86
87 options.SetData(std::move(data));
88 options.SetStream(&stream);
89 options.SetPrefixToken(ElemTraits.first);
90 options.SetQuote('\'');
91 options.SetSourceSize(1);
92 options.SetBinaryZeroIsTerminator(false);
93
94 return StringPrinter::ReadBufferAndDumpToStream<ElemType>(options);
95}
96
97bool lldb_private::formatters::Char8StringSummaryProvider(
98 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
99 return CharStringSummaryProvider<StringElementType::UTF8>(valobj, stream);
100}
101
102bool lldb_private::formatters::Char16StringSummaryProvider(
103 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
104 return CharStringSummaryProvider<StringElementType::UTF16>(valobj, stream);
105}
106
107bool lldb_private::formatters::Char32StringSummaryProvider(
108 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
109 return CharStringSummaryProvider<StringElementType::UTF32>(valobj, stream);
110}
111
112bool lldb_private::formatters::WCharStringSummaryProvider(
113 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
114 Address valobj_addr = GetArrayAddressOrPointerValue(valobj);
115 if (!valobj_addr.IsValid())
116 return false;
117
118 // Get a wchar_t basic type from the current type system
119 CompilerType wchar_compiler_type =
120 valobj.GetCompilerType().GetBasicTypeFromAST(basic_type: lldb::eBasicTypeWChar);
121
122 if (!wchar_compiler_type)
123 return false;
124
125 // Safe to pass nullptr for exe_scope here.
126 std::optional<uint64_t> size =
127 llvm::expectedToOptional(E: wchar_compiler_type.GetBitSize(exe_scope: nullptr));
128 if (!size)
129 return false;
130 const uint32_t wchar_size = *size;
131
132 StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
133 options.SetLocation(valobj_addr);
134 options.SetTargetSP(valobj.GetTargetSP());
135 options.SetStream(&stream);
136 options.SetPrefixToken("L");
137
138 switch (wchar_size) {
139 case 8:
140 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF8>(
141 options);
142 case 16:
143 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF16>(
144 options);
145 case 32:
146 return StringPrinter::ReadStringAndDumpToStream<StringElementType::UTF32>(
147 options);
148 default:
149 stream.Printf(format: "size for wchar_t is not valid");
150 return true;
151 }
152 return true;
153}
154
155bool lldb_private::formatters::Char8SummaryProvider(
156 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
157 return CharSummaryProvider<StringElementType::UTF8>(valobj, stream);
158}
159
160bool lldb_private::formatters::Char16SummaryProvider(
161 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
162 return CharSummaryProvider<StringElementType::UTF16>(valobj, stream);
163}
164
165bool lldb_private::formatters::Char32SummaryProvider(
166 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
167 return CharSummaryProvider<StringElementType::UTF32>(valobj, stream);
168}
169
170bool lldb_private::formatters::WCharSummaryProvider(
171 ValueObject &valobj, Stream &stream, const TypeSummaryOptions &) {
172 DataExtractor data;
173 Status error;
174 valobj.GetData(data, error);
175
176 if (error.Fail())
177 return false;
178
179 // Get a wchar_t basic type from the current type system
180 CompilerType wchar_compiler_type =
181 valobj.GetCompilerType().GetBasicTypeFromAST(basic_type: lldb::eBasicTypeWChar);
182
183 if (!wchar_compiler_type)
184 return false;
185
186 // Safe to pass nullptr for exe_scope here.
187 std::optional<uint64_t> size =
188 llvm::expectedToOptional(E: wchar_compiler_type.GetBitSize(exe_scope: nullptr));
189 if (!size)
190 return false;
191 const uint32_t wchar_size = *size;
192
193 StringPrinter::ReadBufferAndDumpToStreamOptions options(valobj);
194 options.SetData(std::move(data));
195 options.SetStream(&stream);
196 options.SetPrefixToken("L");
197 options.SetQuote('\'');
198 options.SetSourceSize(1);
199 options.SetBinaryZeroIsTerminator(false);
200
201 switch (wchar_size) {
202 case 8:
203 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF8>(
204 options);
205 case 16:
206 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF16>(
207 options);
208 case 32:
209 return StringPrinter::ReadBufferAndDumpToStream<StringElementType::UTF32>(
210 options);
211 default:
212 stream.Printf(format: "size for wchar_t is not valid");
213 return true;
214 }
215 return true;
216}
217

source code of lldb/source/Plugins/Language/CPlusPlus/CxxStringTypes.cpp