StringPrinter.h revision 360784
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
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 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