1 //===---------------------JSON.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 utility_JSON_h_ 11 #define utility_JSON_h_ 12 13 // This cross-project usage is fine as StringExtractor.h is entirely 14 // self-contained. 15 #include "lldb/Utility/StringExtractor.h" 16 17 // C includes 18 #include <inttypes.h> 19 #include <stdint.h> 20 21 // C++ includes 22 #include <map> 23 #include <memory> 24 #include <ostream> 25 #include <string> 26 #include <vector> 27 28 class JSONValue 29 { 30 public: 31 virtual void 32 Write (std::ostream& s) = 0; 33 34 typedef std::shared_ptr<JSONValue> SP; 35 36 enum class Kind 37 { 38 String, 39 Number, 40 True, 41 False, 42 Null, 43 Object, 44 Array 45 }; 46 47 JSONValue (Kind k) : 48 m_kind(k) 49 {} 50 51 Kind 52 GetKind() const 53 { 54 return m_kind; 55 } 56 57 virtual 58 ~JSONValue () = default; 59 60 private: 61 const Kind m_kind; 62 }; 63 64 class JSONString : public JSONValue 65 { 66 public: 67 JSONString (); 68 JSONString (const char* s); 69 JSONString (const std::string& s); 70 71 JSONString (const JSONString& s) = delete; 72 JSONString& 73 operator = (const JSONString& s) = delete; 74 75 void 76 Write(std::ostream& s) override; 77 78 typedef std::shared_ptr<JSONString> SP; 79 80 std::string 81 GetData () { return m_data; } 82 83 static bool classof(const JSONValue *V) 84 { 85 return V->GetKind() == JSONValue::Kind::String; 86 } 87 88 ~JSONString() override = default; 89 90 private: 91 92 static std::string 93 json_string_quote_metachars (const std::string&); 94 95 std::string m_data; 96 }; 97 98 class JSONNumber : public JSONValue 99 { 100 public: 101 typedef std::shared_ptr<JSONNumber> SP; 102 103 // We cretae a constructor for all integer and floating point type with using templates and 104 // SFINAE to avoid having ambiguous overloads because of the implicit type promotion. If we 105 // would have constructors only with int64_t, uint64_t and double types then constructing a 106 // JSONNumber from an int32_t (or any other similar type) would fail to compile. 107 108 template <typename T, 109 typename std::enable_if<std::is_integral<T>::value && 110 std::is_unsigned<T>::value>::type* = nullptr> 111 explicit JSONNumber (T u) : 112 JSONValue(JSONValue::Kind::Number), 113 m_data_type(DataType::Unsigned) 114 { 115 m_data.m_unsigned = u; 116 } 117 118 template <typename T, 119 typename std::enable_if<std::is_integral<T>::value && 120 std::is_signed<T>::value>::type* = nullptr> 121 explicit JSONNumber (T s) : 122 JSONValue(JSONValue::Kind::Number), 123 m_data_type(DataType::Signed) 124 { 125 m_data.m_signed = s; 126 } 127 128 template <typename T, 129 typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr> 130 explicit JSONNumber (T d) : 131 JSONValue(JSONValue::Kind::Number), 132 m_data_type(DataType::Double) 133 { 134 m_data.m_double = d; 135 } 136 137 ~JSONNumber() override = default; 138 139 JSONNumber (const JSONNumber& s) = delete; 140 JSONNumber& 141 operator = (const JSONNumber& s) = delete; 142 143 void 144 Write(std::ostream& s) override; 145 146 uint64_t 147 GetAsUnsigned() const; 148 149 int64_t 150 GetAsSigned() const; 151 152 double 153 GetAsDouble() const; 154 155 static bool classof(const JSONValue *V) 156 { 157 return V->GetKind() == JSONValue::Kind::Number; 158 } 159 160 private: 161 enum class DataType : uint8_t 162 { 163 Unsigned, 164 Signed, 165 Double 166 } m_data_type; 167 168 union 169 { 170 uint64_t m_unsigned; 171 int64_t m_signed; 172 double m_double; 173 } m_data; 174 }; 175 176 class JSONTrue : public JSONValue 177 { 178 public: 179 JSONTrue (); 180 181 JSONTrue (const JSONTrue& s) = delete; 182 JSONTrue& 183 operator = (const JSONTrue& s) = delete; 184 185 void 186 Write(std::ostream& s) override; 187 188 typedef std::shared_ptr<JSONTrue> SP; 189 190 static bool classof(const JSONValue *V) 191 { 192 return V->GetKind() == JSONValue::Kind::True; 193 } 194 195 ~JSONTrue() override = default; 196 }; 197 198 class JSONFalse : public JSONValue 199 { 200 public: 201 JSONFalse (); 202 203 JSONFalse (const JSONFalse& s) = delete; 204 JSONFalse& 205 operator = (const JSONFalse& s) = delete; 206 207 void 208 Write(std::ostream& s) override; 209 210 typedef std::shared_ptr<JSONFalse> SP; 211 212 static bool classof(const JSONValue *V) 213 { 214 return V->GetKind() == JSONValue::Kind::False; 215 } 216 217 ~JSONFalse() override = default; 218 }; 219 220 class JSONNull : public JSONValue 221 { 222 public: 223 JSONNull (); 224 225 JSONNull (const JSONNull& s) = delete; 226 JSONNull& 227 operator = (const JSONNull& s) = delete; 228 229 void 230 Write(std::ostream& s) override; 231 232 typedef std::shared_ptr<JSONNull> SP; 233 234 static bool classof(const JSONValue *V) 235 { 236 return V->GetKind() == JSONValue::Kind::Null; 237 } 238 239 ~JSONNull() override = default; 240 }; 241 242 class JSONObject : public JSONValue 243 { 244 public: 245 JSONObject (); 246 247 JSONObject (const JSONObject& s) = delete; 248 JSONObject& 249 operator = (const JSONObject& s) = delete; 250 251 void 252 Write(std::ostream& s) override; 253 254 typedef std::shared_ptr<JSONObject> SP; 255 256 static bool classof(const JSONValue *V) 257 { 258 return V->GetKind() == JSONValue::Kind::Object; 259 } 260 261 bool 262 SetObject (const std::string& key, 263 JSONValue::SP value); 264 265 JSONValue::SP 266 GetObject (const std::string& key) const; 267 268 // ------------------------------------------------------------------------- 269 /// Return keyed value as bool 270 /// 271 /// @param[in] key 272 /// The value of the key to lookup 273 /// 274 /// @param[out] value 275 /// The value of the key as a bool. Undefined if the key doesn't 276 /// exist or if the key is not either true or false. 277 /// 278 /// @return 279 /// true if the key existed as was a bool value; false otherwise. 280 /// Note the return value is *not* the value of the bool, use 281 /// \b value for that. 282 // ------------------------------------------------------------------------- 283 bool 284 GetObjectAsBool (const std::string& key, bool& value) const; 285 286 bool 287 GetObjectAsString (const std::string& key, std::string& value) const; 288 289 ~JSONObject() override = default; 290 291 private: 292 typedef std::map<std::string, JSONValue::SP> Map; 293 typedef Map::iterator Iterator; 294 Map m_elements; 295 }; 296 297 class JSONArray : public JSONValue 298 { 299 public: 300 JSONArray (); 301 302 JSONArray (const JSONArray& s) = delete; 303 JSONArray& 304 operator = (const JSONArray& s) = delete; 305 306 void 307 Write(std::ostream& s) override; 308 309 typedef std::shared_ptr<JSONArray> SP; 310 311 static bool classof(const JSONValue *V) 312 { 313 return V->GetKind() == JSONValue::Kind::Array; 314 } 315 316 private: 317 typedef std::vector<JSONValue::SP> Vector; 318 typedef Vector::iterator Iterator; 319 typedef Vector::size_type Index; 320 typedef Vector::size_type Size; 321 322 public: 323 bool 324 SetObject (Index i, 325 JSONValue::SP value); 326 327 bool 328 AppendObject (JSONValue::SP value); 329 330 JSONValue::SP 331 GetObject (Index i); 332 333 Size 334 GetNumElements (); 335 336 ~JSONArray() override = default; 337 338 Vector m_elements; 339 }; 340 341 class JSONParser : public StringExtractor 342 { 343 public: 344 enum Token 345 { 346 Invalid, 347 Error, 348 ObjectStart, 349 ObjectEnd, 350 ArrayStart, 351 ArrayEnd, 352 Comma, 353 Colon, 354 String, 355 Integer, 356 Float, 357 True, 358 False, 359 Null, 360 EndOfFile 361 }; 362 363 JSONParser (const char *cstr); 364 365 int 366 GetEscapedChar (bool &was_escaped); 367 368 Token 369 GetToken (std::string &value); 370 371 JSONValue::SP 372 ParseJSONValue (); 373 374 protected: 375 JSONValue::SP 376 ParseJSONObject (); 377 378 JSONValue::SP 379 ParseJSONArray (); 380 }; 381 382 #endif // utility_JSON_h_ 383