brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.9 KiB · 1818250 Raw
391 lines · c
1//===-- JSONGenerator.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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H10#define LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H11 12#include <iomanip>13#include <sstream>14#include <string>15#include <utility>16#include <vector>17 18/// \class JSONGenerator JSONGenerator.h19/// A class which can construct structured data for the sole purpose20/// of printing it in JSON format.21///22/// A stripped down version of lldb's StructuredData objects which are much23/// general purpose.  This variant is intended only for assembling information24/// and printing it as a JSON string.25 26class JSONGenerator {27public:28  class Object;29  class Array;30  class Integer;31  class Float;32  class Boolean;33  class String;34  class Dictionary;35  class Generic;36 37  typedef std::shared_ptr<Object> ObjectSP;38  typedef std::shared_ptr<Array> ArraySP;39  typedef std::shared_ptr<Integer> IntegerSP;40  typedef std::shared_ptr<Float> FloatSP;41  typedef std::shared_ptr<Boolean> BooleanSP;42  typedef std::shared_ptr<String> StringSP;43  typedef std::shared_ptr<Dictionary> DictionarySP;44  typedef std::shared_ptr<Generic> GenericSP;45 46  enum class Type {47    eTypeInvalid = -1,48    eTypeNull = 0,49    eTypeGeneric,50    eTypeArray,51    eTypeInteger,52    eTypeFloat,53    eTypeBoolean,54    eTypeString,55    eTypeDictionary56  };57 58  class Object : public std::enable_shared_from_this<Object> {59  public:60    Object(Type t = Type::eTypeInvalid) : m_type(t) {}61 62    virtual ~Object() {}63 64    virtual bool IsValid() const { return true; }65 66    virtual void Clear() { m_type = Type::eTypeInvalid; }67 68    Type GetType() const { return m_type; }69 70    void SetType(Type t) { m_type = t; }71 72    Array *GetAsArray() {73      if (m_type == Type::eTypeArray)74        return (Array *)this;75      return NULL;76    }77 78    Dictionary *GetAsDictionary() {79      if (m_type == Type::eTypeDictionary)80        return (Dictionary *)this;81      return NULL;82    }83 84    Integer *GetAsInteger() {85      if (m_type == Type::eTypeInteger)86        return (Integer *)this;87      return NULL;88    }89 90    Float *GetAsFloat() {91      if (m_type == Type::eTypeFloat)92        return (Float *)this;93      return NULL;94    }95 96    Boolean *GetAsBoolean() {97      if (m_type == Type::eTypeBoolean)98        return (Boolean *)this;99      return NULL;100    }101 102    String *GetAsString() {103      if (m_type == Type::eTypeString)104        return (String *)this;105      return NULL;106    }107 108    Generic *GetAsGeneric() {109      if (m_type == Type::eTypeGeneric)110        return (Generic *)this;111      return NULL;112    }113 114    virtual void Dump(std::ostream &s) const = 0;115 116    virtual void DumpBinaryEscaped(std::ostream &s) const = 0;117 118  private:119    Type m_type;120  };121 122  class Array : public Object {123  public:124    Array() : Object(Type::eTypeArray) {}125 126    virtual ~Array() {}127 128    void AddItem(ObjectSP item) { m_items.push_back(item); }129 130    void Dump(std::ostream &s) const override {131      s << "[";132      const size_t arrsize = m_items.size();133      for (size_t i = 0; i < arrsize; ++i) {134        m_items[i]->Dump(s);135        if (i + 1 < arrsize)136          s << ",";137      }138      s << "]";139    }140 141    void DumpBinaryEscaped(std::ostream &s) const override {142      s << "[";143      const size_t arrsize = m_items.size();144      for (size_t i = 0; i < arrsize; ++i) {145        m_items[i]->DumpBinaryEscaped(s);146        if (i + 1 < arrsize)147          s << ",";148      }149      s << "]";150    }151 152  protected:153    typedef std::vector<ObjectSP> collection;154    collection m_items;155  };156 157  class Integer : public Object {158  public:159    Integer(uint64_t value = 0) : Object(Type::eTypeInteger), m_value(value) {}160 161    virtual ~Integer() {}162 163    void SetValue(uint64_t value) { m_value = value; }164 165    void Dump(std::ostream &s) const override { s << m_value; }166 167    void DumpBinaryEscaped(std::ostream &s) const override { Dump(s); }168 169  protected:170    uint64_t m_value;171  };172 173  class Float : public Object {174  public:175    Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}176 177    virtual ~Float() {}178 179    void SetValue(double value) { m_value = value; }180 181    void Dump(std::ostream &s) const override { s << m_value; }182 183    void DumpBinaryEscaped(std::ostream &s) const override { Dump(s); }184 185  protected:186    double m_value;187  };188 189  class Boolean : public Object {190  public:191    Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}192 193    virtual ~Boolean() {}194 195    void SetValue(bool value) { m_value = value; }196 197    void Dump(std::ostream &s) const override {198      if (m_value)199        s << "true";200      else201        s << "false";202    }203 204    void DumpBinaryEscaped(std::ostream &s) const override { Dump(s); }205 206  protected:207    bool m_value;208  };209 210  class String : public Object {211  public:212    String() : Object(Type::eTypeString), m_value() {}213 214    String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}215 216    String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}217 218    void SetValue(const std::string &string) { m_value = string; }219 220    void Dump(std::ostream &s) const override {221      s << '"';222      const size_t strsize = m_value.size();223      for (size_t i = 0; i < strsize; ++i) {224        char ch = m_value[i];225        if (ch == '"')226          s << '\\';227        s << ch;228      }229      s << '"';230    }231 232    void DumpBinaryEscaped(std::ostream &s) const override {233      s << '"';234      const size_t strsize = m_value.size();235      for (size_t i = 0; i < strsize; ++i) {236        char ch = m_value[i];237        if (ch == '"')238          s << '\\';239        // gdb remote serial protocol binary escaping240        if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {241          s << '}'; // 0x7d next character is escaped242          s << static_cast<char>(ch ^ 0x20);243        } else {244          s << ch;245        }246      }247      s << '"';248    }249 250  protected:251    std::string m_value;252  };253 254  class Dictionary : public Object {255  public:256    Dictionary() : Object(Type::eTypeDictionary), m_dict() {}257 258    virtual ~Dictionary() {}259 260    void AddItem(std::string key, ObjectSP value) {261      m_dict.push_back(Pair(key, value));262    }263 264    void AddIntegerItem(std::string key, uint64_t value) {265      AddItem(key, ObjectSP(new Integer(value)));266    }267 268    void AddFloatItem(std::string key, double value) {269      AddItem(key, ObjectSP(new Float(value)));270    }271 272    void AddStringItem(std::string key, std::string value) {273      AddItem(key, ObjectSP(new String(std::move(value))));274    }275 276    void AddBytesAsHexASCIIString(std::string key, const uint8_t *src,277                                  size_t src_len) {278      if (src && src_len) {279        std::ostringstream strm;280        for (size_t i = 0; i < src_len; i++)281          strm << std::setfill('0') << std::hex << std::right << std::setw(2)282               << ((uint32_t)(src[i]));283        AddItem(key, ObjectSP(new String(std::move(strm.str()))));284      } else {285        AddItem(key, ObjectSP(new String()));286      }287    }288 289    void AddBooleanItem(std::string key, bool value) {290      AddItem(key, ObjectSP(new Boolean(value)));291    }292 293    void Dump(std::ostream &s) const override {294      bool have_printed_one_elem = false;295      s << "{";296      for (collection::const_iterator iter = m_dict.begin();297           iter != m_dict.end(); ++iter) {298        if (!have_printed_one_elem) {299          have_printed_one_elem = true;300        } else {301          s << ",";302        }303        s << "\"" << iter->first.c_str() << "\":";304        iter->second->Dump(s);305      }306      s << "}";307    }308 309    void DumpBinaryEscaped(std::ostream &s) const override {310      bool have_printed_one_elem = false;311      s << "{";312      for (collection::const_iterator iter = m_dict.begin();313           iter != m_dict.end(); ++iter) {314        if (!have_printed_one_elem) {315          have_printed_one_elem = true;316        } else {317          s << ",";318        }319        s << "\"" << binary_encode_string(iter->first) << "\":";320        iter->second->DumpBinaryEscaped(s);321      }322      // '}' must be escaped for the gdb remote serial323      // protocol.324      s << "}";325      s << static_cast<char>('}' ^ 0x20);326    }327 328  protected:329    std::string binary_encode_string(const std::string &s) const {330      std::string output;331      const size_t s_size = s.size();332      const char *s_chars = s.c_str();333 334      for (size_t i = 0; i < s_size; i++) {335        unsigned char ch = *(s_chars + i);336        if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {337          output.push_back('}'); // 0x7d338          output.push_back(ch ^ 0x20);339        } else {340          output.push_back(ch);341        }342      }343      return output;344    }345 346    // Keep the dictionary as a vector so the dictionary doesn't reorder itself347    // when you dump it348    // We aren't accessing keys by name, so this won't affect performance349    typedef std::pair<std::string, ObjectSP> Pair;350    typedef std::vector<Pair> collection;351    collection m_dict;352  };353 354  class Null : public Object {355  public:356    Null() : Object(Type::eTypeNull) {}357 358    virtual ~Null() {}359 360    bool IsValid() const override { return false; }361 362    void Dump(std::ostream &s) const override { s << "null"; }363 364    void DumpBinaryEscaped(std::ostream &s) const override { Dump(s); }365 366  protected:367  };368 369  class Generic : public Object {370  public:371    explicit Generic(void *object = nullptr)372        : Object(Type::eTypeGeneric), m_object(object) {}373 374    void SetValue(void *value) { m_object = value; }375 376    void *GetValue() const { return m_object; }377 378    bool IsValid() const override { return m_object != nullptr; }379 380    void Dump(std::ostream &s) const override;381 382    void DumpBinaryEscaped(std::ostream &s) const override;383 384  private:385    void *m_object;386  };387 388}; // class JSONGenerator389 390#endif // LLDB_TOOLS_DEBUGSERVER_SOURCE_JSONGENERATOR_H391