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