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