aizatsky updated this revision to Diff 70879.
aizatsky added a comment.

remove .clang-tidy


https://reviews.llvm.org/D24369

Files:
  include/llvm/Support/JSON.h
  lib/Support/CMakeLists.txt
  lib/Support/JSON.cpp
  unittests/Support/CMakeLists.txt
  unittests/Support/JSONTest.cpp

Index: unittests/Support/JSONTest.cpp
===================================================================
--- /dev/null
+++ unittests/Support/JSONTest.cpp
@@ -0,0 +1,46 @@
+//===- llvm/unittest/Support/JSONTest.cpp - JSON.cpp tests ---===//
+//
+//		       The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+#include "llvm/Support/JSON.h"
+
+using namespace llvm;
+
+static ::testing::AssertionResult MatchRoundtrip(std::string Text) {
+  JSONParser Parser(Text.c_str());
+  auto Obj = Parser.parseJSONValue();
+
+  if (!Obj) {
+    return Text == "null"
+               ? ::testing::AssertionSuccess()
+               : ::testing::AssertionFailure() << "can't parse input: " << Text;
+  }
+
+  std::string S;
+  raw_string_ostream Out(S);
+  Obj->write(Out);
+
+  std::string Actual = Out.str();
+  if (Actual != Text) {
+    return ::testing::AssertionFailure() << "expected: " << Text
+                                         << " actual: " << Actual;
+  }
+  return ::testing::AssertionSuccess();
+}
+
+TEST(JSON, Roundtrip) {
+  EXPECT_TRUE(MatchRoundtrip("0"));
+  EXPECT_TRUE(MatchRoundtrip("3.145150e+00"));
+  EXPECT_TRUE(MatchRoundtrip("{}"));
+  EXPECT_TRUE(MatchRoundtrip("{\"a\":1,\"b\":2}"));
+  EXPECT_TRUE(MatchRoundtrip("[]"));
+  EXPECT_TRUE(MatchRoundtrip("[0]"));
+  EXPECT_TRUE(MatchRoundtrip("[1,\"two\",3]"));
+}
Index: unittests/Support/CMakeLists.txt
===================================================================
--- unittests/Support/CMakeLists.txt
+++ unittests/Support/CMakeLists.txt
@@ -19,6 +19,7 @@
   ErrorTest.cpp
   ErrorOrTest.cpp
   FileOutputBufferTest.cpp
+  JSONTest.cpp
   LEB128Test.cpp
   LineIteratorTest.cpp
   LockFileManagerTest.cpp
Index: lib/Support/JSON.cpp
===================================================================
--- /dev/null
+++ lib/Support/JSON.cpp
@@ -0,0 +1,595 @@
+//===--------------------- JSON.cpp -----------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/JSON.h"
+
+#include <limits.h>
+#include <sstream>
+
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+std::string JSONString::jsonStringQuoteMetachars(const std::string &S) {
+  if (S.find('"') == std::string::npos)
+    return S;
+
+  std::string Output;
+  const size_t Size = S.size();
+  const char *Chars = S.c_str();
+  for (size_t I = 0; I < Size; I++) {
+    unsigned char Ch = *(Chars + I);
+    if (Ch == '"') {
+      Output.push_back('\\');
+    }
+    Output.push_back(Ch);
+  }
+  return Output;
+}
+
+JSONString::JSONString() : JSONValue(JSONValue::Kind::String), Data() {}
+
+JSONString::JSONString(const char *S)
+    : JSONValue(JSONValue::Kind::String), Data(S ? S : "") {}
+
+JSONString::JSONString(const std::string &S)
+    : JSONValue(JSONValue::Kind::String), Data(S) {}
+
+void JSONString::write(raw_ostream &OS) const {
+  OS << "\"" << jsonStringQuoteMetachars(Data) << "\"";
+}
+
+uint64_t JSONNumber::getAsUnsigned() const {
+  switch (TheDataType) {
+  case DataType::Unsigned:
+    return Data.Unsigned;
+  case DataType::Signed:
+    return (uint64_t)Data.Signed;
+  case DataType::Double:
+    return (uint64_t)Data.Double;
+  }
+  llvm_unreachable("Unhandled data type");
+}
+
+int64_t JSONNumber::getAsSigned() const {
+  switch (TheDataType) {
+  case DataType::Unsigned:
+    return (int64_t)Data.Unsigned;
+  case DataType::Signed:
+    return Data.Signed;
+  case DataType::Double:
+    return (int64_t)Data.Double;
+  }
+  llvm_unreachable("Unhandled data type");
+}
+
+double JSONNumber::getAsDouble() const {
+  switch (TheDataType) {
+  case DataType::Unsigned:
+    return (double)Data.Unsigned;
+  case DataType::Signed:
+    return (double)Data.Signed;
+  case DataType::Double:
+    return Data.Double;
+  }
+  llvm_unreachable("Unhandled data type");
+}
+
+void JSONNumber::write(raw_ostream &OS) const {
+  switch (TheDataType) {
+  case DataType::Unsigned:
+    OS << Data.Unsigned;
+    break;
+  case DataType::Signed:
+    OS << Data.Signed;
+    break;
+  case DataType::Double:
+    OS << Data.Double;
+    break;
+  }
+}
+
+JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {}
+
+void JSONTrue::write(raw_ostream &OS) const { OS << "true"; }
+
+JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {}
+
+void JSONFalse::write(raw_ostream &OS) const { OS << "false"; }
+
+JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {}
+
+void JSONNull::write(raw_ostream &OS) const { OS << "null"; }
+
+JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {}
+
+void JSONObject::write(raw_ostream &OS) const {
+  bool First = true;
+  OS << '{';
+  auto Iter = Elements.begin(), End = Elements.end();
+  for (; Iter != End; Iter++) {
+    if (First)
+      First = false;
+    else
+      OS << ',';
+    JSONString Key(Iter->first);
+    JSONValue::SP Value(Iter->second);
+    Key.write(OS);
+    OS << ':';
+    Value->write(OS);
+  }
+  OS << '}';
+}
+
+bool JSONObject::setObject(const std::string &Key, JSONValue::SP Value) {
+  if (Key.empty() || nullptr == Value.get())
+    return false;
+  Elements[Key] = Value;
+  return true;
+}
+
+JSONValue::SP JSONObject::getObject(const std::string &Key) {
+  auto Iter = Elements.find(Key), End = Elements.end();
+  if (Iter == End)
+    return JSONValue::SP();
+  return Iter->second;
+}
+
+JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {}
+
+void JSONArray::write(raw_ostream &OS) const {
+  bool First = true;
+  OS << '[';
+  auto Iter = Elements.begin(), End = Elements.end();
+  for (; Iter != End; Iter++) {
+    if (First)
+      First = false;
+    else
+      OS << ',';
+    (*Iter)->write(OS);
+  }
+  OS << ']';
+}
+
+bool JSONArray::setObject(Index I, JSONValue::SP Value) {
+  if (Value.get() == nullptr)
+    return false;
+  if (I < Elements.size()) {
+    Elements[I] = Value;
+    return true;
+  }
+  if (I == Elements.size()) {
+    Elements.push_back(Value);
+    return true;
+  }
+  return false;
+}
+
+bool JSONArray::appendObject(JSONValue::SP Value) {
+  if (Value.get() == nullptr)
+    return false;
+  Elements.push_back(Value);
+  return true;
+}
+
+JSONValue::SP JSONArray::getObject(Index I) {
+  if (I < Elements.size())
+    return Elements[I];
+  return JSONValue::SP();
+}
+
+JSONArray::Size JSONArray::getNumElements() { return Elements.size(); }
+
+JSONParser::JSONParser(const char *CStr) : Index(0) {
+  if (CStr)
+    Buffer.assign(CStr);
+}
+
+JSONParser::Token JSONParser::getToken(std::string &Value) {
+  std::stringstream Error;
+
+  Value.clear();
+  skipSpaces();
+  const uint64_t StartIndex = Index;
+  const char Ch = getChar();
+  switch (Ch) {
+  case '{':
+    return Token::ObjectStart;
+  case '}':
+    return Token::ObjectEnd;
+  case '[':
+    return Token::ArrayStart;
+  case ']':
+    return Token::ArrayEnd;
+  case ',':
+    return Token::Comma;
+  case ':':
+    return Token::Colon;
+  case '\0':
+    return Token::EndOfFile;
+  case 't':
+    if (getChar() == 'r')
+      if (getChar() == 'u')
+        if (getChar() == 'e')
+          return Token::True;
+    break;
+
+  case 'f':
+    if (getChar() == 'a')
+      if (getChar() == 'l')
+        if (getChar() == 's')
+          if (getChar() == 'e')
+            return Token::False;
+    break;
+
+  case 'n':
+    if (getChar() == 'u')
+      if (getChar() == 'l')
+        if (getChar() == 'l')
+          return Token::Null;
+    break;
+
+  case '"': {
+    while (1) {
+      bool WasEscaped = false;
+      int EscapedCh = getEscapedChar(WasEscaped);
+      if (EscapedCh == -1) {
+        Error << "error: an error occurred getting a character from offset "
+              << StartIndex;
+        Value = Error.str();
+        return Token::Error;
+
+      } else {
+        const bool IsEndQuote = EscapedCh == '"';
+        const bool IsNull = EscapedCh == 0;
+        if (WasEscaped || (!IsEndQuote && !IsNull)) {
+          if (CHAR_MIN <= EscapedCh && EscapedCh <= CHAR_MAX) {
+            Value.append(1, (char)EscapedCh);
+          } else {
+            Error << "error: wide character support is needed for unicode "
+                     "character 0x"
+                  << std::hex << EscapedCh << std::dec << " at offset "
+                  << StartIndex;
+            Value = Error.str();
+            return Token::Error;
+          }
+        } else if (IsEndQuote) {
+          return Token::String;
+        } else if (IsNull) {
+          Value = "error: missing end quote for string";
+          return Token::Error;
+        }
+      }
+    }
+  } break;
+
+  case '-':
+  case '0':
+  case '1':
+  case '2':
+  case '3':
+  case '4':
+  case '5':
+  case '6':
+  case '7':
+  case '8':
+  case '9': {
+    uint64_t ExpIndex = 0;
+    bool Done = false;
+    bool GotDecimalPoint = false;
+    bool GotIntDigits = (Ch >= '0') && (Ch <= '9');
+    bool GotFracDigits = false;
+    bool GotExpDigits = false;
+    while (!Done) {
+      const char NextCh = peekChar();
+      switch (NextCh) {
+      case '0':
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        if (ExpIndex != 0) {
+          GotExpDigits = true;
+        } else if (GotDecimalPoint) {
+          GotFracDigits = true;
+        } else {
+          GotIntDigits = true;
+        }
+        ++Index; // Skip this character
+        break;
+
+      case '.':
+        if (GotDecimalPoint) {
+          Error << "error: extra decimal point found at offset " << StartIndex;
+          Value = Error.str();
+          return Token::Error;
+        } else {
+          GotDecimalPoint = true;
+          ++Index; // Skip this character
+        }
+        break;
+
+      case 'e':
+      case 'E':
+        if (ExpIndex != 0) {
+          Error << "error: extra exponent character found at offset "
+                << StartIndex;
+          Value = Error.str();
+          return Token::Error;
+        } else {
+          ExpIndex = Index;
+          ++Index; // Skip this character
+        }
+        break;
+
+      case '+':
+      case '-':
+        // The '+' and '-' can only come after an exponent character...
+        if (ExpIndex == Index - 1) {
+          ++Index; // Skip the exponent sign character
+        } else {
+          Error << "error: unexpected " << NextCh << " character at offset "
+                << StartIndex;
+          Value = Error.str();
+          return Token::Error;
+        }
+        break;
+
+      default:
+        Done = true;
+        break;
+      }
+    }
+
+    if (Index > StartIndex) {
+      Value = Buffer.substr(StartIndex, Index - StartIndex);
+      if (GotDecimalPoint) {
+        if (ExpIndex != 0) {
+          // We have an exponent, make sure we got exponent digits
+          if (GotExpDigits) {
+            return Token::Float;
+          } else {
+            Error << "error: got exponent character but no exponent digits at "
+                     "offset in float value \""
+                  << Value << "\"";
+            Value = Error.str();
+            return Token::Error;
+          }
+        } else {
+          // No exponent, but we need at least one decimal after the decimal
+          // point
+          if (GotFracDigits) {
+            return Token::Float;
+          } else {
+            Error << "error: no digits after decimal point \"" << Value << "\"";
+            Value = Error.str();
+            return Token::Error;
+          }
+        }
+      } else {
+        // No decimal point
+        if (GotIntDigits) {
+          // We need at least some integer digits to make an integer
+          return Token::Integer;
+        } else {
+          Error << "error: no digits negate sign \"" << Value << "%s\"";
+          Value = Error.str();
+          return Token::Error;
+        }
+      }
+    } else {
+      Error << "error: invalid number found at offset " << StartIndex;
+      Value = Error.str();
+      return Token::Error;
+    }
+  } break;
+  default:
+    break;
+  }
+  Error << "error: failed to parse token at offset " << StartIndex
+        << " (around character '" << Ch << "')";
+  Value = Error.str();
+  return Token::Error;
+}
+
+int JSONParser::getEscapedChar(bool &WasEscaped) {
+  WasEscaped = false;
+  const char Ch = getChar();
+  if (Ch == '\\') {
+    WasEscaped = true;
+    const char Ch2 = getChar();
+    switch (Ch2) {
+    case '"':
+    case '\\':
+    case '/':
+    default:
+      break;
+
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'u': {
+      const int HiByte = decodeHexU8();
+      const int LoByte = decodeHexU8();
+      if (HiByte >= 0 && LoByte >= 0)
+        return HiByte << 8 | LoByte;
+      return -1;
+    } break;
+    }
+    return Ch2;
+  }
+  return Ch;
+}
+
+JSONValue::SP JSONParser::parseJSONObject() {
+  // The "JSONParser::Token::ObjectStart" token should have already been
+  // consumed
+  // by the time this function is called
+  std::unique_ptr<JSONObject> DictUp(new JSONObject());
+
+  std::string Value;
+  std::string Key;
+  while (1) {
+    JSONParser::Token Token = getToken(Value);
+
+    if (Token == JSONParser::Token::String) {
+      Key.swap(Value);
+      Token = getToken(Value);
+      if (Token == JSONParser::Token::Colon) {
+        JSONValue::SP ValueSP = parseJSONValue();
+        if (ValueSP)
+          DictUp->setObject(Key, ValueSP);
+        else
+          break;
+      }
+    } else if (Token == JSONParser::Token::ObjectEnd) {
+      return JSONValue::SP(DictUp.release());
+    } else if (Token == JSONParser::Token::Comma) {
+      continue;
+    } else {
+      break;
+    }
+  }
+  return JSONValue::SP();
+}
+
+JSONValue::SP JSONParser::parseJSONArray() {
+  // The "JSONParser::Token::ObjectStart" token should have already been
+  // consumed
+  // by the time this function is called
+  std::unique_ptr<JSONArray> ArrayUp(new JSONArray());
+
+  std::string Value;
+  while (1) {
+    skipSpaces();
+
+    char Peek = peekChar();
+    if (Peek == ']' || Peek == ',') {
+      JSONParser::Token Token = getToken(Value);
+      if (Token == JSONParser::Token::Comma) {
+        continue;
+      } else if (Token == JSONParser::Token::ArrayEnd) {
+        return JSONValue::SP(ArrayUp.release());
+      }
+    }
+
+    JSONValue::SP ValueSP = parseJSONValue();
+    if (ValueSP)
+      ArrayUp->appendObject(ValueSP);
+    else
+      break;
+  }
+  return JSONValue::SP();
+}
+
+JSONValue::SP JSONParser::parseJSONValue() {
+  std::string Value;
+  const JSONParser::Token Token = getToken(Value);
+  switch (Token) {
+  case JSONParser::Token::ObjectStart:
+    return parseJSONObject();
+
+  case JSONParser::Token::ArrayStart:
+    return parseJSONArray();
+
+  case JSONParser::Token::Integer: {
+    char *End = nullptr;
+    if (Value.front() == '-') {
+      int64_t SVal = ::strtoll(Value.c_str(), &End, 10);
+      bool Success = *End == '\0'; // all characters were used.
+      if (Success)
+        return JSONValue::SP(new JSONNumber(SVal));
+    } else {
+      uint64_t UVal = ::strtoul(Value.c_str(), &End, 10);
+      bool Success = *End == '\0'; // all characters were used.
+      if (Success)
+        return JSONValue::SP(new JSONNumber(UVal));
+    }
+  } break;
+
+  case JSONParser::Token::Float: {
+    char *End = nullptr;
+    double Val = ::strtod(Value.c_str(), &End);
+    bool Success = *End == '\0'; // all characters were used.
+    if (Success)
+      return JSONValue::SP(new JSONNumber(Val));
+  } break;
+
+  case JSONParser::Token::String:
+    return JSONValue::SP(new JSONString(Value));
+
+  case JSONParser::Token::True:
+    return JSONValue::SP(new JSONTrue());
+
+  case JSONParser::Token::False:
+    return JSONValue::SP(new JSONFalse());
+
+  case JSONParser::Token::Null:
+    return JSONValue::SP(new JSONNull());
+
+  default:
+    break;
+  }
+  return JSONValue::SP();
+}
+
+void JSONParser::skipSpaces() {
+  const size_t S = Buffer.size();
+  while (Index < S && isspace(Buffer[Index]))
+    ++Index;
+}
+
+char JSONParser::getChar() {
+  if (getBytesLeft() < 1)
+    return 0;
+  return Buffer[Index++];
+}
+
+char JSONParser::peekChar() const {
+  if (getBytesLeft() == 0)
+    return 0;
+
+  return Buffer[Index];
+}
+
+static inline int hexDigitToSInt(char Ch) {
+  if (Ch >= 'a' && Ch <= 'f')
+    return 10 + Ch - 'a';
+  if (Ch >= 'A' && Ch <= 'F')
+    return 10 + Ch - 'A';
+  if (Ch >= '0' && Ch <= '9')
+    return Ch - '0';
+  return -1;
+}
+
+uint8_t JSONParser::decodeHexU8() {
+  skipSpaces();
+  if (getBytesLeft() < 2) {
+    return -1;
+  }
+  const int HiNibble = hexDigitToSInt(Buffer[Index]);
+  const int LoNibble = hexDigitToSInt(Buffer[Index + 1]);
+  if (HiNibble == -1 || LoNibble == -1) {
+    return -1;
+  }
+  Index += 2;
+  return (uint8_t)((HiNibble << 4) + LoNibble);
+}
Index: lib/Support/CMakeLists.txt
===================================================================
--- lib/Support/CMakeLists.txt
+++ lib/Support/CMakeLists.txt
@@ -61,6 +61,7 @@
   IntervalMap.cpp
   IntrusiveRefCntPtr.cpp
   JamCRC.cpp
+  JSON.cpp
   LEB128.cpp
   LineIterator.cpp
   Locale.cpp
Index: include/llvm/Support/JSON.h
===================================================================
--- /dev/null
+++ include/llvm/Support/JSON.h
@@ -0,0 +1,287 @@
+//===---------------------JSON.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_JSON_H
+#define LLVM_SUPPORT_JSON_H
+
+#include <inttypes.h>
+#include <map>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+class JSONValue {
+public:
+  typedef std::shared_ptr<JSONValue> SP;
+  enum class Kind { String, Number, True, False, Null, Object, Array };
+
+  JSONValue(Kind K) : TheKind(K) {}
+  virtual ~JSONValue() = default;
+
+  virtual void write(raw_ostream &S) const = 0;
+
+  Kind getKind() const { return TheKind; }
+
+private:
+  const Kind TheKind;
+};
+
+class JSONString : public JSONValue {
+public:
+  typedef std::shared_ptr<JSONString> SP;
+
+  JSONString();
+  JSONString(const char *S);
+  JSONString(const std::string &S);
+
+  JSONString(const JSONString &S) = delete;
+  JSONString &operator=(const JSONString &S) = delete;
+
+  ~JSONString() override = default;
+
+  void write(raw_ostream &S) const override;
+
+  std::string getData() const { return Data; }
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::String;
+  }
+
+private:
+  static std::string jsonStringQuoteMetachars(const std::string &);
+
+  std::string Data;
+};
+
+class JSONNumber : public JSONValue {
+public:
+  typedef std::shared_ptr<JSONNumber> SP;
+
+  // We cretae a constructor for all integer and floating point type with using
+  // templates and
+  // SFINAE to avoid having ambiguous overloads because of the implicit type
+  // promotion. If we
+  // would have constructors only with int64_t, uint64_t and double types then
+  // constructing a
+  // JSONNumber from an int32_t (or any other similar type) would fail to
+  // compile.
+
+  template <typename T, typename std::enable_if<
+                            std::is_integral<T>::value &&
+                            std::is_unsigned<T>::value>::type * = nullptr>
+  explicit JSONNumber(T U)
+      : JSONValue(JSONValue::Kind::Number), TheDataType(DataType::Unsigned) {
+    Data.Unsigned = U;
+  }
+
+  template <typename T,
+            typename std::enable_if<std::is_integral<T>::value &&
+                                    std::is_signed<T>::value>::type * = nullptr>
+  explicit JSONNumber(T S)
+      : JSONValue(JSONValue::Kind::Number), TheDataType(DataType::Signed) {
+    Data.Signed = S;
+  }
+
+  template <typename T, typename std::enable_if<
+                            std::is_floating_point<T>::value>::type * = nullptr>
+  explicit JSONNumber(T D)
+      : JSONValue(JSONValue::Kind::Number), TheDataType(DataType::Double) {
+    Data.Double = D;
+  }
+
+  ~JSONNumber() override = default;
+
+  JSONNumber(const JSONNumber &S) = delete;
+  JSONNumber &operator=(const JSONNumber &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  uint64_t getAsUnsigned() const;
+
+  int64_t getAsSigned() const;
+
+  double getAsDouble() const;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::Number;
+  }
+
+private:
+  enum class DataType : uint8_t { Unsigned, Signed, Double } TheDataType;
+
+  union {
+    uint64_t Unsigned;
+    int64_t Signed;
+    double Double;
+  } Data;
+};
+
+class JSONTrue : public JSONValue {
+public:
+  JSONTrue();
+
+  JSONTrue(const JSONTrue &S) = delete;
+  JSONTrue &operator=(const JSONTrue &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  typedef std::shared_ptr<JSONTrue> SP;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::True;
+  }
+
+  ~JSONTrue() override = default;
+};
+
+class JSONFalse : public JSONValue {
+public:
+  JSONFalse();
+
+  JSONFalse(const JSONFalse &S) = delete;
+  JSONFalse &operator=(const JSONFalse &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  typedef std::shared_ptr<JSONFalse> SP;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::False;
+  }
+
+  ~JSONFalse() override = default;
+};
+
+class JSONNull : public JSONValue {
+public:
+  JSONNull();
+
+  JSONNull(const JSONNull &S) = delete;
+  JSONNull &operator=(const JSONNull &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  typedef std::shared_ptr<JSONNull> SP;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::Null;
+  }
+
+  ~JSONNull() override = default;
+};
+
+class JSONObject : public JSONValue {
+public:
+  JSONObject();
+
+  JSONObject(const JSONObject &S) = delete;
+  JSONObject &operator=(const JSONObject &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  typedef std::shared_ptr<JSONObject> SP;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::Object;
+  }
+
+  bool setObject(const std::string &Key, JSONValue::SP Value);
+
+  JSONValue::SP getObject(const std::string &Key);
+
+  ~JSONObject() override = default;
+
+private:
+  typedef std::map<std::string, JSONValue::SP> Map;
+  typedef Map::iterator Iterator;
+  Map Elements;
+};
+
+class JSONArray : public JSONValue {
+public:
+  JSONArray();
+
+  JSONArray(const JSONArray &S) = delete;
+  JSONArray &operator=(const JSONArray &S) = delete;
+
+  void write(raw_ostream &S) const override;
+
+  typedef std::shared_ptr<JSONArray> SP;
+
+  static bool classof(const JSONValue *V) {
+    return V->getKind() == JSONValue::Kind::Array;
+  }
+
+private:
+  typedef std::vector<JSONValue::SP> Vector;
+  typedef Vector::iterator Iterator;
+  typedef Vector::size_type Index;
+  typedef Vector::size_type Size;
+
+public:
+  bool setObject(Index I, JSONValue::SP Value);
+
+  bool appendObject(JSONValue::SP Value);
+
+  JSONValue::SP getObject(Index I);
+
+  Size getNumElements();
+
+  ~JSONArray() override = default;
+
+  Vector Elements;
+};
+
+class JSONParser {
+public:
+  enum Token {
+    Invalid,
+    Error,
+    ObjectStart,
+    ObjectEnd,
+    ArrayStart,
+    ArrayEnd,
+    Comma,
+    Colon,
+    String,
+    Integer,
+    Float,
+    True,
+    False,
+    Null,
+    EndOfFile
+  };
+
+  JSONParser(const char *Cstr);
+  JSONValue::SP parseJSONValue();
+
+protected:
+  int getEscapedChar(bool &WasEscaped);
+  Token getToken(std::string &Value);
+  JSONValue::SP parseJSONObject();
+  JSONValue::SP parseJSONArray();
+
+  void skipSpaces();
+  uint8_t decodeHexU8();
+  char getChar();
+  char peekChar() const;
+  size_t getBytesLeft() const { return Buffer.size() - Index; }
+
+  std::string Buffer;
+  size_t Index;
+};
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_JSON_H
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to