text: //===-- FormatEntity.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 LLDB_CORE_FORMATENTITY_H
  #define LLDB_CORE_FORMATENTITY_H
  
  #include "lldb/lldb-enumerations.h"
  #include "lldb/lldb-types.h"
  #include <algorithm>
  #include <cstddef>
  #include <cstdint>
  
  #include <string>
  #include <vector>
  
  namespace lldb_private {
  class Address;
  class CompletionRequest;
  class ExecutionContext;
  class FileSpec;
  class Status;
  class Stream;
  class StringList;
  class SymbolContext;
  class ValueObject;
  }
  
  namespace llvm {
  class StringRef;
  }
  
  namespace lldb_private {
  class FormatEntity {
  public:
    struct Entry {
      enum class Type {
        Invalid,
        ParentNumber,
        ParentString,
        EscapeCode,
        Root,
        String,
        Scope,
        Variable,
        VariableSynthetic,
        ScriptVariable,
        ScriptVariableSynthetic,
        AddressLoad,
        AddressFile,
        AddressLoadOrFile,
        ProcessID,
        ProcessFile,
        ScriptProcess,
        ThreadID,
        ThreadProtocolID,
        ThreadIndexID,
        ThreadName,
        ThreadQueue,
        ThreadStopReason,
        ThreadStopReasonRaw,
        ThreadReturnValue,
        ThreadCompletedExpression,
        ScriptThread,
        ThreadInfo,
        TargetArch,
        ScriptTarget,
        ModuleFile,
        File,
        Lang,
        FrameIndex,
        FrameNoDebug,
        FrameRegisterPC,
        FrameRegisterSP,
        FrameRegisterFP,
        FrameRegisterFlags,
        FrameRegisterByName,
        FrameIsArtificial,
        ScriptFrame,
        FunctionID,
        FunctionDidChange,
        FunctionInitialFunction,
        FunctionName,
        FunctionNameWithArgs,
        FunctionNameNoArgs,
        FunctionMangledName,
        FunctionAddrOffset,
        FunctionAddrOffsetConcrete,
        FunctionLineOffset,
        FunctionPCOffset,
        FunctionInitial,
        FunctionChanged,
        FunctionIsOptimized,
        LineEntryFile,
        LineEntryLineNumber,
        LineEntryColumn,
        LineEntryStartAddress,
        LineEntryEndAddress,
        CurrentPCArrow
      };
  
      struct Definition {
        /// The name/string placeholder that corresponds to this definition.
        const char *name;
        /// Insert this exact string into the output
        const char *string = nullptr;
        /// Entry::Type corresponding to this definition.
        const Entry::Type type;
        /// Data that is returned as the value of the format string.
        const uint64_t data = 0;
        /// The number of children of this node in the tree of format strings.
        const uint32_t num_children = 0;
        /// An array of "num_children" Definition entries.
        const Definition *children = nullptr;
        /// Whether the separator is kept during parsing or not.  It's used
        /// for entries with parameters.
        const bool keep_separator = false;
  
        constexpr Definition(const char *name, const FormatEntity::Entry::Type t)
            : name(name), type(t) {}
  
        constexpr Definition(const char *name, const char *string)
            : name(name), string(string), type(Entry::Type::EscapeCode) {}
  
        constexpr Definition(const char *name, const FormatEntity::Entry::Type t,
                             const uint64_t data)
            : name(name), type(t), data(data) {}
  
        constexpr Definition(const char *name, const FormatEntity::Entry::Type t,
                             const uint64_t num_children,
                             const Definition *children,
                             const bool keep_separator = false)
            : name(name), type(t), num_children(num_children), children(children),
              keep_separator(keep_separator) {}
      };
  
      template <size_t N>
      static constexpr Definition
      DefinitionWithChildren(const char *name, const FormatEntity::Entry::Type t,
                             const Definition (&children)[N],
                             bool keep_separator = false) {
        return Definition(name, t, N, children, keep_separator);
      }
  
      Entry(Type t = Type::Invalid, const char *s = nullptr,
            const char *f = nullptr)
          : string(s ? s : ""), printf_format(f ? f : ""), type(t) {}
  
      Entry(llvm::StringRef s);
      Entry(char ch);
  
      void AppendChar(char ch);
  
      void AppendText(const llvm::StringRef &s);
  
      void AppendText(const char *cstr);
  
      void AppendEntry(const Entry &&entry) { children.push_back(entry); }
  
      void Clear() {
        string.clear();
        printf_format.clear();
        children.clear();
        type = Type::Invalid;
        fmt = lldb::eFormatDefault;
        number = 0;
        deref = false;
      }
  
      static const char *TypeToCString(Type t);
  
      void Dump(Stream &s, int depth = 0) const;
  
      bool operator==(const Entry &rhs) const {
        if (string != rhs.string)
          return false;
        if (printf_format != rhs.printf_format)
          return false;
        const size_t n = children.size();
        const size_t m = rhs.children.size();
        for (size_t i = 0; i < std::min<size_t>(n, m); ++i) {
          if (!(children[i] == rhs.children[i]))
            return false;
        }
        if (children != rhs.children)
          return false;
        if (type != rhs.type)
          return false;
        if (fmt != rhs.fmt)
          return false;
        if (deref != rhs.deref)
          return false;
        return true;
      }
  
      std::string string;
      std::string printf_format;
      std::vector<Entry> children;
      Type type;
      lldb::Format fmt = lldb::eFormatDefault;
      lldb::addr_t number = 0;
      bool deref = false;
    };
  
    static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc,
                       const ExecutionContext *exe_ctx, const Address *addr,
                       ValueObject *valobj, bool function_changed,
                       bool initial_function);
  
    static bool FormatStringRef(const llvm::StringRef &format, Stream &s,
                                const SymbolContext *sc,
                                const ExecutionContext *exe_ctx,
                                const Address *addr, ValueObject *valobj,
                                bool function_changed, bool initial_function);
  
    static bool FormatCString(const char *format, Stream &s,
                              const SymbolContext *sc,
                              const ExecutionContext *exe_ctx,
                              const Address *addr, ValueObject *valobj,
                              bool function_changed, bool initial_function);
  
    static Status Parse(const llvm::StringRef &format, Entry &entry);
  
    static Status ExtractVariableInfo(llvm::StringRef &format_str,
                                      llvm::StringRef &variable_name,
                                      llvm::StringRef &variable_format);
  
    static void AutoComplete(lldb_private::CompletionRequest &request);
  
    // Format the current elements into the stream \a s.
    //
    // The root element will be stripped off and the format str passed in will be
    // either an empty string (print a description of this object), or contain a
    // `.`-separated series like a domain name that identifies further
    //  sub-elements to display.
    static bool FormatFileSpec(const FileSpec &file, Stream &s,
                               llvm::StringRef elements,
                               llvm::StringRef element_format);
  
  protected:
    static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry,
                                uint32_t depth);
  };
  } // namespace lldb_private
  
  #endif // LLDB_CORE_FORMATENTITY_H
  