reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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_