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