blob: 41d5edd880216d21026dee33af86f8afaf354277 [file] [log] [blame]
Andrew Walbran3d2c1972020-04-07 12:24:26 +01001//===-- StringPrinter.h -----------------------------------------*- C++ -*-===//
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#ifndef liblldb_StringPrinter_h_
10#define liblldb_StringPrinter_h_
11
12#include <functional>
13#include <string>
14
15#include "lldb/lldb-forward.h"
16
17#include "lldb/Utility/DataExtractor.h"
18
19namespace lldb_private {
20namespace formatters {
21class StringPrinter {
22public:
23 enum class StringElementType { ASCII, UTF8, UTF16, UTF32 };
24
25 enum class GetPrintableElementType { ASCII, UTF8 };
26
27 class ReadStringAndDumpToStreamOptions {
28 public:
29 ReadStringAndDumpToStreamOptions()
30 : m_location(0), m_process_sp(), m_stream(nullptr), m_prefix_token(),
31 m_suffix_token(), m_quote('"'), m_source_size(0),
32 m_needs_zero_termination(true), m_escape_non_printables(true),
33 m_ignore_max_length(false), m_zero_is_terminator(true),
34 m_language_type(lldb::eLanguageTypeUnknown) {}
35
36 ReadStringAndDumpToStreamOptions(ValueObject &valobj);
37
38 ReadStringAndDumpToStreamOptions &SetLocation(uint64_t l) {
39 m_location = l;
40 return *this;
41 }
42
43 uint64_t GetLocation() const { return m_location; }
44
45 ReadStringAndDumpToStreamOptions &SetProcessSP(lldb::ProcessSP p) {
46 m_process_sp = p;
47 return *this;
48 }
49
50 lldb::ProcessSP GetProcessSP() const { return m_process_sp; }
51
52 ReadStringAndDumpToStreamOptions &SetStream(Stream *s) {
53 m_stream = s;
54 return *this;
55 }
56
57 Stream *GetStream() const { return m_stream; }
58
59 ReadStringAndDumpToStreamOptions &SetPrefixToken(const std::string &p) {
60 m_prefix_token = p;
61 return *this;
62 }
63
64 ReadStringAndDumpToStreamOptions &SetPrefixToken(std::nullptr_t) {
65 m_prefix_token.clear();
66 return *this;
67 }
68
69 const char *GetPrefixToken() const { return m_prefix_token.c_str(); }
70
71 ReadStringAndDumpToStreamOptions &SetSuffixToken(const std::string &p) {
72 m_suffix_token = p;
73 return *this;
74 }
75
76 ReadStringAndDumpToStreamOptions &SetSuffixToken(std::nullptr_t) {
77 m_suffix_token.clear();
78 return *this;
79 }
80
81 const char *GetSuffixToken() const { return m_suffix_token.c_str(); }
82
83 ReadStringAndDumpToStreamOptions &SetQuote(char q) {
84 m_quote = q;
85 return *this;
86 }
87
88 char GetQuote() const { return m_quote; }
89
90 ReadStringAndDumpToStreamOptions &SetSourceSize(uint32_t s) {
91 m_source_size = s;
92 return *this;
93 }
94
95 uint32_t GetSourceSize() const { return m_source_size; }
96
97 ReadStringAndDumpToStreamOptions &SetNeedsZeroTermination(bool z) {
98 m_needs_zero_termination = z;
99 return *this;
100 }
101
102 bool GetNeedsZeroTermination() const { return m_needs_zero_termination; }
103
104 ReadStringAndDumpToStreamOptions &SetBinaryZeroIsTerminator(bool e) {
105 m_zero_is_terminator = e;
106 return *this;
107 }
108
109 bool GetBinaryZeroIsTerminator() const { return m_zero_is_terminator; }
110
111 ReadStringAndDumpToStreamOptions &SetEscapeNonPrintables(bool e) {
112 m_escape_non_printables = e;
113 return *this;
114 }
115
116 bool GetEscapeNonPrintables() const { return m_escape_non_printables; }
117
118 ReadStringAndDumpToStreamOptions &SetIgnoreMaxLength(bool e) {
119 m_ignore_max_length = e;
120 return *this;
121 }
122
123 bool GetIgnoreMaxLength() const { return m_ignore_max_length; }
124
125 ReadStringAndDumpToStreamOptions &SetLanguage(lldb::LanguageType l) {
126 m_language_type = l;
127 return *this;
128 }
129
130 lldb::LanguageType GetLanguage() const
131
132 {
133 return m_language_type;
134 }
135
136 private:
137 uint64_t m_location;
138 lldb::ProcessSP m_process_sp;
139 Stream *m_stream;
140 std::string m_prefix_token;
141 std::string m_suffix_token;
142 char m_quote;
143 uint32_t m_source_size;
144 bool m_needs_zero_termination;
145 bool m_escape_non_printables;
146 bool m_ignore_max_length;
147 bool m_zero_is_terminator;
148 lldb::LanguageType m_language_type;
149 };
150
151 class ReadBufferAndDumpToStreamOptions {
152 public:
153 ReadBufferAndDumpToStreamOptions()
154 : m_data(), m_stream(nullptr), m_prefix_token(), m_suffix_token(),
155 m_quote('"'), m_source_size(0), m_escape_non_printables(true),
156 m_zero_is_terminator(true), m_is_truncated(false),
157 m_language_type(lldb::eLanguageTypeUnknown) {}
158
159 ReadBufferAndDumpToStreamOptions(ValueObject &valobj);
160
161 ReadBufferAndDumpToStreamOptions(
162 const ReadStringAndDumpToStreamOptions &options);
163
164 ReadBufferAndDumpToStreamOptions &SetData(DataExtractor d) {
165 m_data = d;
166 return *this;
167 }
168
169 lldb_private::DataExtractor GetData() const { return m_data; }
170
171 ReadBufferAndDumpToStreamOptions &SetStream(Stream *s) {
172 m_stream = s;
173 return *this;
174 }
175
176 Stream *GetStream() const { return m_stream; }
177
178 ReadBufferAndDumpToStreamOptions &SetPrefixToken(const std::string &p) {
179 m_prefix_token = p;
180 return *this;
181 }
182
183 ReadBufferAndDumpToStreamOptions &SetPrefixToken(std::nullptr_t) {
184 m_prefix_token.clear();
185 return *this;
186 }
187
188 const char *GetPrefixToken() const { return m_prefix_token.c_str(); }
189
190 ReadBufferAndDumpToStreamOptions &SetSuffixToken(const std::string &p) {
191 m_suffix_token = p;
192 return *this;
193 }
194
195 ReadBufferAndDumpToStreamOptions &SetSuffixToken(std::nullptr_t) {
196 m_suffix_token.clear();
197 return *this;
198 }
199
200 const char *GetSuffixToken() const { return m_suffix_token.c_str(); }
201
202 ReadBufferAndDumpToStreamOptions &SetQuote(char q) {
203 m_quote = q;
204 return *this;
205 }
206
207 char GetQuote() const { return m_quote; }
208
209 ReadBufferAndDumpToStreamOptions &SetSourceSize(uint32_t s) {
210 m_source_size = s;
211 return *this;
212 }
213
214 uint32_t GetSourceSize() const { return m_source_size; }
215
216 ReadBufferAndDumpToStreamOptions &SetEscapeNonPrintables(bool e) {
217 m_escape_non_printables = e;
218 return *this;
219 }
220
221 bool GetEscapeNonPrintables() const { return m_escape_non_printables; }
222
223 ReadBufferAndDumpToStreamOptions &SetBinaryZeroIsTerminator(bool e) {
224 m_zero_is_terminator = e;
225 return *this;
226 }
227
228 bool GetBinaryZeroIsTerminator() const { return m_zero_is_terminator; }
229
230 ReadBufferAndDumpToStreamOptions &SetIsTruncated(bool t) {
231 m_is_truncated = t;
232 return *this;
233 }
234
235 bool GetIsTruncated() const { return m_is_truncated; }
236
237 ReadBufferAndDumpToStreamOptions &SetLanguage(lldb::LanguageType l) {
238 m_language_type = l;
239 return *this;
240 }
241
242 lldb::LanguageType GetLanguage() const
243
244 {
245 return m_language_type;
246 }
247
248 private:
249 DataExtractor m_data;
250 Stream *m_stream;
251 std::string m_prefix_token;
252 std::string m_suffix_token;
253 char m_quote;
254 uint32_t m_source_size;
255 bool m_escape_non_printables;
256 bool m_zero_is_terminator;
257 bool m_is_truncated;
258 lldb::LanguageType m_language_type;
259 };
260
261 // I can't use a std::unique_ptr for this because the Deleter is a template
262 // argument there
263 // and I want the same type to represent both pointers I want to free and
264 // pointers I don't need to free - which is what this class essentially is
265 // It's very specialized to the needs of this file, and not suggested for
266 // general use
267 template <typename T = uint8_t, typename U = char, typename S = size_t>
268 struct StringPrinterBufferPointer {
269 public:
270 typedef std::function<void(const T *)> Deleter;
271
272 StringPrinterBufferPointer(std::nullptr_t ptr)
273 : m_data(nullptr), m_size(0), m_deleter() {}
274
275 StringPrinterBufferPointer(const T *bytes, S size,
276 Deleter deleter = nullptr)
277 : m_data(bytes), m_size(size), m_deleter(deleter) {}
278
279 StringPrinterBufferPointer(const U *bytes, S size,
280 Deleter deleter = nullptr)
281 : m_data(reinterpret_cast<const T *>(bytes)), m_size(size),
282 m_deleter(deleter) {}
283
284 StringPrinterBufferPointer(StringPrinterBufferPointer &&rhs)
285 : m_data(rhs.m_data), m_size(rhs.m_size), m_deleter(rhs.m_deleter) {
286 rhs.m_data = nullptr;
287 }
288
289 StringPrinterBufferPointer(const StringPrinterBufferPointer &rhs)
290 : m_data(rhs.m_data), m_size(rhs.m_size), m_deleter(rhs.m_deleter) {
291 rhs.m_data = nullptr; // this is why m_data has to be mutable
292 }
293
294 ~StringPrinterBufferPointer() {
295 if (m_data && m_deleter)
296 m_deleter(m_data);
297 m_data = nullptr;
298 }
299
300 const T *GetBytes() const { return m_data; }
301
302 const S GetSize() const { return m_size; }
303
304 StringPrinterBufferPointer &
305 operator=(const StringPrinterBufferPointer &rhs) {
306 if (m_data && m_deleter)
307 m_deleter(m_data);
308 m_data = rhs.m_data;
309 m_size = rhs.m_size;
310 m_deleter = rhs.m_deleter;
311 rhs.m_data = nullptr;
312 return *this;
313 }
314
315 private:
316 mutable const T *m_data;
317 size_t m_size;
318 Deleter m_deleter;
319 };
320
321 typedef std::function<StringPrinter::StringPrinterBufferPointer<
322 uint8_t, char, size_t>(uint8_t *, uint8_t *, uint8_t *&)>
323 EscapingHelper;
324 typedef std::function<EscapingHelper(GetPrintableElementType)>
325 EscapingHelperGenerator;
326
327 static EscapingHelper
328 GetDefaultEscapingHelper(GetPrintableElementType elem_type);
329
330 template <StringElementType element_type>
331 static bool
332 ReadStringAndDumpToStream(const ReadStringAndDumpToStreamOptions &options);
333
334 template <StringElementType element_type>
335 static bool
336 ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options);
337};
338
339} // namespace formatters
340} // namespace lldb_private
341
342#endif // liblldb_StringPrinter_h_