1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
| //===-- StringPrinter.h -----------------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_StringPrinter_h_
#define liblldb_StringPrinter_h_
#include <functional>
#include <string>
#include "lldb/lldb-forward.h"
#include "lldb/Utility/DataExtractor.h"
namespace lldb_private {
namespace formatters {
class StringPrinter {
public:
enum class StringElementType { ASCII, UTF8, UTF16, UTF32 };
enum class GetPrintableElementType { ASCII, UTF8 };
class DumpToStreamOptions {
public:
DumpToStreamOptions() = default;
void SetStream(Stream *s) { m_stream = s; }
Stream *GetStream() const { return m_stream; }
void SetPrefixToken(const std::string &p) { m_prefix_token = p; }
void SetPrefixToken(std::nullptr_t) { m_prefix_token.clear(); }
const char *GetPrefixToken() const { return m_prefix_token.c_str(); }
void SetSuffixToken(const std::string &p) { m_suffix_token = p; }
void SetSuffixToken(std::nullptr_t) { m_suffix_token.clear(); }
const char *GetSuffixToken() const { return m_suffix_token.c_str(); }
void SetQuote(char q) { m_quote = q; }
char GetQuote() const { return m_quote; }
void SetSourceSize(uint32_t s) { m_source_size = s; }
uint32_t GetSourceSize() const { return m_source_size; }
void SetNeedsZeroTermination(bool z) { m_needs_zero_termination = z; }
bool GetNeedsZeroTermination() const { return m_needs_zero_termination; }
void SetBinaryZeroIsTerminator(bool e) { m_zero_is_terminator = e; }
bool GetBinaryZeroIsTerminator() const { return m_zero_is_terminator; }
void SetEscapeNonPrintables(bool e) { m_escape_non_printables = e; }
bool GetEscapeNonPrintables() const { return m_escape_non_printables; }
void SetIgnoreMaxLength(bool e) { m_ignore_max_length = e; }
bool GetIgnoreMaxLength() const { return m_ignore_max_length; }
void SetLanguage(lldb::LanguageType l) { m_language_type = l; }
lldb::LanguageType GetLanguage() const { return m_language_type; }
private:
/// The used output stream.
Stream *m_stream = nullptr;
/// String that should be printed before the heading quote character.
std::string m_prefix_token;
/// String that should be printed after the trailing quote character.
std::string m_suffix_token;
/// The quote character that should surround the string.
char m_quote = '"';
/// The length of the memory region that should be dumped in bytes.
uint32_t m_source_size = 0;
bool m_needs_zero_termination = true;
/// True iff non-printable characters should be escaped when dumping
/// them to the stream.
bool m_escape_non_printables = true;
/// True iff the max-string-summary-length setting of the target should
/// be ignored.
bool m_ignore_max_length = false;
/// True iff a zero bytes ('\0') should terminate the memory region that
/// is being dumped.
bool m_zero_is_terminator = true;
/// The language that the generated string literal is supposed to be valid
/// for. This changes for example what and how certain characters are
/// escaped.
/// For example, printing the a string containing only a quote (") char
/// with eLanguageTypeC would escape the quote character.
lldb::LanguageType m_language_type = lldb::eLanguageTypeUnknown;
};
class ReadStringAndDumpToStreamOptions : public DumpToStreamOptions {
public:
ReadStringAndDumpToStreamOptions() = default;
ReadStringAndDumpToStreamOptions(ValueObject &valobj);
void SetLocation(uint64_t l) { m_location = l; }
uint64_t GetLocation() const { return m_location; }
void SetProcessSP(lldb::ProcessSP p) { m_process_sp = p; }
lldb::ProcessSP GetProcessSP() const { return m_process_sp; }
private:
uint64_t m_location = 0;
lldb::ProcessSP m_process_sp;
};
class ReadBufferAndDumpToStreamOptions : public DumpToStreamOptions {
public:
ReadBufferAndDumpToStreamOptions() = default;
ReadBufferAndDumpToStreamOptions(ValueObject &valobj);
ReadBufferAndDumpToStreamOptions(
const ReadStringAndDumpToStreamOptions &options);
void SetData(DataExtractor d) { m_data = d; }
lldb_private::DataExtractor GetData() const { return m_data; }
void SetIsTruncated(bool t) { m_is_truncated = t; }
bool GetIsTruncated() const { return m_is_truncated; }
private:
DataExtractor m_data;
bool m_is_truncated = false;
};
// I can't use a std::unique_ptr for this because the Deleter is a template
// argument there
// and I want the same type to represent both pointers I want to free and
// pointers I don't need to free - which is what this class essentially is
// It's very specialized to the needs of this file, and not suggested for
// general use
template <typename T = uint8_t, typename U = char, typename S = size_t>
struct StringPrinterBufferPointer {
public:
typedef std::function<void(const T *)> Deleter;
StringPrinterBufferPointer(std::nullptr_t ptr)
: m_data(nullptr), m_size(0), m_deleter() {}
StringPrinterBufferPointer(const T *bytes, S size,
Deleter deleter = nullptr)
: m_data(bytes), m_size(size), m_deleter(deleter) {}
StringPrinterBufferPointer(const U *bytes, S size,
Deleter deleter = nullptr)
: m_data(reinterpret_cast<const T *>(bytes)), m_size(size),
m_deleter(deleter) {}
StringPrinterBufferPointer(StringPrinterBufferPointer &&rhs)
: m_data(rhs.m_data), m_size(rhs.m_size), m_deleter(rhs.m_deleter) {
rhs.m_data = nullptr;
}
StringPrinterBufferPointer(const StringPrinterBufferPointer &rhs)
: m_data(rhs.m_data), m_size(rhs.m_size), m_deleter(rhs.m_deleter) {
rhs.m_data = nullptr; // this is why m_data has to be mutable
}
~StringPrinterBufferPointer() {
if (m_data && m_deleter)
m_deleter(m_data);
m_data = nullptr;
}
const T *GetBytes() const { return m_data; }
const S GetSize() const { return m_size; }
StringPrinterBufferPointer &
operator=(const StringPrinterBufferPointer &rhs) {
if (m_data && m_deleter)
m_deleter(m_data);
m_data = rhs.m_data;
m_size = rhs.m_size;
m_deleter = rhs.m_deleter;
rhs.m_data = nullptr;
return *this;
}
private:
mutable const T *m_data;
size_t m_size;
Deleter m_deleter;
};
typedef std::function<StringPrinter::StringPrinterBufferPointer<
uint8_t, char, size_t>(uint8_t *, uint8_t *, uint8_t *&)>
EscapingHelper;
typedef std::function<EscapingHelper(GetPrintableElementType)>
EscapingHelperGenerator;
static EscapingHelper
GetDefaultEscapingHelper(GetPrintableElementType elem_type);
template <StringElementType element_type>
static bool
ReadStringAndDumpToStream(const ReadStringAndDumpToStreamOptions &options);
template <StringElementType element_type>
static bool
ReadBufferAndDumpToStream(const ReadBufferAndDumpToStreamOptions &options);
};
} // namespace formatters
} // namespace lldb_private
#endif // liblldb_StringPrinter_h_
|