1061da546Spatrick //===--------------------- JSON.cpp -----------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "JSON.h" 10061da546Spatrick 11061da546Spatrick // C includes 12*be691f3bSpatrick #include <cassert> 13*be691f3bSpatrick #include <climits> 14061da546Spatrick 15061da546Spatrick // C++ includes 16061da546Spatrick #include "lldb/Host/StringConvert.h" 17061da546Spatrick #include <iomanip> 18061da546Spatrick #include <sstream> 19061da546Spatrick 20061da546Spatrick using namespace lldb_private; 21061da546Spatrick 22061da546Spatrick std::string JSONString::json_string_quote_metachars(const std::string &s) { 23061da546Spatrick if (s.find('"') == std::string::npos) 24061da546Spatrick return s; 25061da546Spatrick 26061da546Spatrick std::string output; 27061da546Spatrick const size_t s_size = s.size(); 28061da546Spatrick const char *s_chars = s.c_str(); 29061da546Spatrick for (size_t i = 0; i < s_size; i++) { 30061da546Spatrick unsigned char ch = *(s_chars + i); 31061da546Spatrick if (ch == '"') { 32061da546Spatrick output.push_back('\\'); 33061da546Spatrick } 34061da546Spatrick output.push_back(ch); 35061da546Spatrick } 36061da546Spatrick return output; 37061da546Spatrick } 38061da546Spatrick 39061da546Spatrick JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {} 40061da546Spatrick 41061da546Spatrick JSONString::JSONString(const char *s) 42061da546Spatrick : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {} 43061da546Spatrick 44061da546Spatrick JSONString::JSONString(const std::string &s) 45061da546Spatrick : JSONValue(JSONValue::Kind::String), m_data(s) {} 46061da546Spatrick 47061da546Spatrick void JSONString::Write(std::ostream &s) { 48061da546Spatrick s << "\"" << json_string_quote_metachars(m_data).c_str() << "\""; 49061da546Spatrick } 50061da546Spatrick 51061da546Spatrick uint64_t JSONNumber::GetAsUnsigned() const { 52061da546Spatrick switch (m_data_type) { 53061da546Spatrick case DataType::Unsigned: 54061da546Spatrick return m_data.m_unsigned; 55061da546Spatrick case DataType::Signed: 56061da546Spatrick return (uint64_t)m_data.m_signed; 57061da546Spatrick case DataType::Double: 58061da546Spatrick return (uint64_t)m_data.m_double; 59061da546Spatrick } 60061da546Spatrick } 61061da546Spatrick 62061da546Spatrick int64_t JSONNumber::GetAsSigned() const { 63061da546Spatrick switch (m_data_type) { 64061da546Spatrick case DataType::Unsigned: 65061da546Spatrick return (int64_t)m_data.m_unsigned; 66061da546Spatrick case DataType::Signed: 67061da546Spatrick return m_data.m_signed; 68061da546Spatrick case DataType::Double: 69061da546Spatrick return (int64_t)m_data.m_double; 70061da546Spatrick } 71061da546Spatrick } 72061da546Spatrick 73061da546Spatrick double JSONNumber::GetAsDouble() const { 74061da546Spatrick switch (m_data_type) { 75061da546Spatrick case DataType::Unsigned: 76061da546Spatrick return (double)m_data.m_unsigned; 77061da546Spatrick case DataType::Signed: 78061da546Spatrick return (double)m_data.m_signed; 79061da546Spatrick case DataType::Double: 80061da546Spatrick return m_data.m_double; 81061da546Spatrick } 82061da546Spatrick } 83061da546Spatrick 84061da546Spatrick void JSONNumber::Write(std::ostream &s) { 85061da546Spatrick switch (m_data_type) { 86061da546Spatrick case DataType::Unsigned: 87061da546Spatrick s << m_data.m_unsigned; 88061da546Spatrick break; 89061da546Spatrick case DataType::Signed: 90061da546Spatrick s << m_data.m_signed; 91061da546Spatrick break; 92061da546Spatrick case DataType::Double: 93061da546Spatrick // Set max precision to emulate %g. 94061da546Spatrick s << std::setprecision(std::numeric_limits<double>::digits10 + 1); 95061da546Spatrick s << m_data.m_double; 96061da546Spatrick break; 97061da546Spatrick } 98061da546Spatrick } 99061da546Spatrick 100061da546Spatrick JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {} 101061da546Spatrick 102061da546Spatrick void JSONTrue::Write(std::ostream &s) { s << "true"; } 103061da546Spatrick 104061da546Spatrick JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {} 105061da546Spatrick 106061da546Spatrick void JSONFalse::Write(std::ostream &s) { s << "false"; } 107061da546Spatrick 108061da546Spatrick JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {} 109061da546Spatrick 110061da546Spatrick void JSONNull::Write(std::ostream &s) { s << "null"; } 111061da546Spatrick 112061da546Spatrick JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {} 113061da546Spatrick 114061da546Spatrick void JSONObject::Write(std::ostream &s) { 115061da546Spatrick bool first = true; 116061da546Spatrick s << '{'; 117061da546Spatrick auto iter = m_elements.begin(), end = m_elements.end(); 118061da546Spatrick for (; iter != end; iter++) { 119061da546Spatrick if (first) 120061da546Spatrick first = false; 121061da546Spatrick else 122061da546Spatrick s << ','; 123061da546Spatrick JSONString key(iter->first); 124061da546Spatrick JSONValue::SP value(iter->second); 125061da546Spatrick key.Write(s); 126061da546Spatrick s << ':'; 127061da546Spatrick value->Write(s); 128061da546Spatrick } 129061da546Spatrick s << '}'; 130061da546Spatrick } 131061da546Spatrick 132061da546Spatrick bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) { 133061da546Spatrick if (key.empty() || nullptr == value.get()) 134061da546Spatrick return false; 135061da546Spatrick m_elements[key] = value; 136061da546Spatrick return true; 137061da546Spatrick } 138061da546Spatrick 139061da546Spatrick JSONValue::SP JSONObject::GetObject(const std::string &key) const { 140061da546Spatrick auto iter = m_elements.find(key), end = m_elements.end(); 141061da546Spatrick if (iter == end) 142061da546Spatrick return JSONValue::SP(); 143061da546Spatrick return iter->second; 144061da546Spatrick } 145061da546Spatrick 146061da546Spatrick bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const { 147061da546Spatrick auto value_sp = GetObject(key); 148061da546Spatrick if (!value_sp) { 149061da546Spatrick // The given key doesn't exist, so we have no value. 150061da546Spatrick return false; 151061da546Spatrick } 152061da546Spatrick 153061da546Spatrick if (JSONTrue::classof(value_sp.get())) { 154061da546Spatrick // We have the value, and it is true. 155061da546Spatrick value = true; 156061da546Spatrick return true; 157061da546Spatrick } else if (JSONFalse::classof(value_sp.get())) { 158061da546Spatrick // We have the value, and it is false. 159061da546Spatrick value = false; 160061da546Spatrick return true; 161061da546Spatrick } else { 162061da546Spatrick // We don't have a valid bool value for the given key. 163061da546Spatrick return false; 164061da546Spatrick } 165061da546Spatrick } 166061da546Spatrick 167061da546Spatrick bool JSONObject::GetObjectAsString(const std::string &key, 168061da546Spatrick std::string &value) const { 169061da546Spatrick auto value_sp = GetObject(key); 170061da546Spatrick if (!value_sp) { 171061da546Spatrick // The given key doesn't exist, so we have no value. 172061da546Spatrick return false; 173061da546Spatrick } 174061da546Spatrick 175061da546Spatrick if (!JSONString::classof(value_sp.get())) 176061da546Spatrick return false; 177061da546Spatrick 178061da546Spatrick value = static_cast<JSONString *>(value_sp.get())->GetData(); 179061da546Spatrick return true; 180061da546Spatrick } 181061da546Spatrick 182061da546Spatrick JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {} 183061da546Spatrick 184061da546Spatrick void JSONArray::Write(std::ostream &s) { 185061da546Spatrick bool first = true; 186061da546Spatrick s << '['; 187061da546Spatrick auto iter = m_elements.begin(), end = m_elements.end(); 188061da546Spatrick for (; iter != end; iter++) { 189061da546Spatrick if (first) 190061da546Spatrick first = false; 191061da546Spatrick else 192061da546Spatrick s << ','; 193061da546Spatrick (*iter)->Write(s); 194061da546Spatrick } 195061da546Spatrick s << ']'; 196061da546Spatrick } 197061da546Spatrick 198061da546Spatrick bool JSONArray::SetObject(Index i, JSONValue::SP value) { 199061da546Spatrick if (value.get() == nullptr) 200061da546Spatrick return false; 201061da546Spatrick if (i < m_elements.size()) { 202061da546Spatrick m_elements[i] = value; 203061da546Spatrick return true; 204061da546Spatrick } 205061da546Spatrick if (i == m_elements.size()) { 206061da546Spatrick m_elements.push_back(value); 207061da546Spatrick return true; 208061da546Spatrick } 209061da546Spatrick return false; 210061da546Spatrick } 211061da546Spatrick 212061da546Spatrick bool JSONArray::AppendObject(JSONValue::SP value) { 213061da546Spatrick if (value.get() == nullptr) 214061da546Spatrick return false; 215061da546Spatrick m_elements.push_back(value); 216061da546Spatrick return true; 217061da546Spatrick } 218061da546Spatrick 219061da546Spatrick JSONValue::SP JSONArray::GetObject(Index i) { 220061da546Spatrick if (i < m_elements.size()) 221061da546Spatrick return m_elements[i]; 222061da546Spatrick return JSONValue::SP(); 223061da546Spatrick } 224061da546Spatrick 225061da546Spatrick JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); } 226061da546Spatrick 227061da546Spatrick JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {} 228061da546Spatrick 229061da546Spatrick JSONParser::Token JSONParser::GetToken(std::string &value) { 230061da546Spatrick std::ostringstream error; 231061da546Spatrick 232061da546Spatrick value.clear(); 233061da546Spatrick SkipSpaces(); 234061da546Spatrick const uint64_t start_index = m_index; 235061da546Spatrick const char ch = GetChar(); 236061da546Spatrick switch (ch) { 237061da546Spatrick case '{': 238061da546Spatrick return Token::ObjectStart; 239061da546Spatrick case '}': 240061da546Spatrick return Token::ObjectEnd; 241061da546Spatrick case '[': 242061da546Spatrick return Token::ArrayStart; 243061da546Spatrick case ']': 244061da546Spatrick return Token::ArrayEnd; 245061da546Spatrick case ',': 246061da546Spatrick return Token::Comma; 247061da546Spatrick case ':': 248061da546Spatrick return Token::Colon; 249061da546Spatrick case '\0': 250061da546Spatrick return Token::EndOfFile; 251061da546Spatrick case 't': 252061da546Spatrick if (GetChar() == 'r') 253061da546Spatrick if (GetChar() == 'u') 254061da546Spatrick if (GetChar() == 'e') 255061da546Spatrick return Token::True; 256061da546Spatrick break; 257061da546Spatrick 258061da546Spatrick case 'f': 259061da546Spatrick if (GetChar() == 'a') 260061da546Spatrick if (GetChar() == 'l') 261061da546Spatrick if (GetChar() == 's') 262061da546Spatrick if (GetChar() == 'e') 263061da546Spatrick return Token::False; 264061da546Spatrick break; 265061da546Spatrick 266061da546Spatrick case 'n': 267061da546Spatrick if (GetChar() == 'u') 268061da546Spatrick if (GetChar() == 'l') 269061da546Spatrick if (GetChar() == 'l') 270061da546Spatrick return Token::Null; 271061da546Spatrick break; 272061da546Spatrick 273061da546Spatrick case '"': { 274061da546Spatrick while (true) { 275061da546Spatrick bool was_escaped = false; 276061da546Spatrick int escaped_ch = GetEscapedChar(was_escaped); 277061da546Spatrick if (escaped_ch == -1) { 278061da546Spatrick error << "error: an error occurred getting a character from offset " 279061da546Spatrick << start_index; 280061da546Spatrick value = error.str(); 281061da546Spatrick return Token::Status; 282061da546Spatrick 283061da546Spatrick } else { 284061da546Spatrick const bool is_end_quote = escaped_ch == '"'; 285061da546Spatrick const bool is_null = escaped_ch == 0; 286061da546Spatrick if (was_escaped || (!is_end_quote && !is_null)) { 287061da546Spatrick if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) { 288061da546Spatrick value.append(1, (char)escaped_ch); 289061da546Spatrick } else { 290061da546Spatrick error << "error: wide character support is needed for unicode " 291061da546Spatrick "character 0x" 292061da546Spatrick << std::setprecision(4) << std::hex << escaped_ch; 293061da546Spatrick error << " at offset " << start_index; 294061da546Spatrick value = error.str(); 295061da546Spatrick return Token::Status; 296061da546Spatrick } 297061da546Spatrick } else if (is_end_quote) { 298061da546Spatrick return Token::String; 299061da546Spatrick } else if (is_null) { 300061da546Spatrick value = "error: missing end quote for string"; 301061da546Spatrick return Token::Status; 302061da546Spatrick } 303061da546Spatrick } 304061da546Spatrick } 305061da546Spatrick } break; 306061da546Spatrick 307061da546Spatrick case '-': 308061da546Spatrick case '0': 309061da546Spatrick case '1': 310061da546Spatrick case '2': 311061da546Spatrick case '3': 312061da546Spatrick case '4': 313061da546Spatrick case '5': 314061da546Spatrick case '6': 315061da546Spatrick case '7': 316061da546Spatrick case '8': 317061da546Spatrick case '9': { 318061da546Spatrick bool done = false; 319061da546Spatrick bool got_decimal_point = false; 320061da546Spatrick uint64_t exp_index = 0; 321061da546Spatrick bool got_int_digits = (ch >= '0') && (ch <= '9'); 322061da546Spatrick bool got_frac_digits = false; 323061da546Spatrick bool got_exp_digits = false; 324061da546Spatrick while (!done) { 325061da546Spatrick const char next_ch = PeekChar(); 326061da546Spatrick switch (next_ch) { 327061da546Spatrick case '0': 328061da546Spatrick case '1': 329061da546Spatrick case '2': 330061da546Spatrick case '3': 331061da546Spatrick case '4': 332061da546Spatrick case '5': 333061da546Spatrick case '6': 334061da546Spatrick case '7': 335061da546Spatrick case '8': 336061da546Spatrick case '9': 337061da546Spatrick if (exp_index != 0) { 338061da546Spatrick got_exp_digits = true; 339061da546Spatrick } else if (got_decimal_point) { 340061da546Spatrick got_frac_digits = true; 341061da546Spatrick } else { 342061da546Spatrick got_int_digits = true; 343061da546Spatrick } 344061da546Spatrick ++m_index; // Skip this character 345061da546Spatrick break; 346061da546Spatrick 347061da546Spatrick case '.': 348061da546Spatrick if (got_decimal_point) { 349061da546Spatrick error << "error: extra decimal point found at offset " << start_index; 350061da546Spatrick value = error.str(); 351061da546Spatrick return Token::Status; 352061da546Spatrick } else { 353061da546Spatrick got_decimal_point = true; 354061da546Spatrick ++m_index; // Skip this character 355061da546Spatrick } 356061da546Spatrick break; 357061da546Spatrick 358061da546Spatrick case 'e': 359061da546Spatrick case 'E': 360061da546Spatrick if (exp_index != 0) { 361061da546Spatrick error << "error: extra exponent character found at offset " 362061da546Spatrick << start_index; 363061da546Spatrick value = error.str(); 364061da546Spatrick return Token::Status; 365061da546Spatrick } else { 366061da546Spatrick exp_index = m_index; 367061da546Spatrick ++m_index; // Skip this character 368061da546Spatrick } 369061da546Spatrick break; 370061da546Spatrick 371061da546Spatrick case '+': 372061da546Spatrick case '-': 373061da546Spatrick // The '+' and '-' can only come after an exponent character... 374061da546Spatrick if (exp_index == m_index - 1) { 375061da546Spatrick ++m_index; // Skip the exponent sign character 376061da546Spatrick } else { 377061da546Spatrick error << "error: unexpected " << next_ch << " character at offset " 378061da546Spatrick << start_index; 379061da546Spatrick value = error.str(); 380061da546Spatrick return Token::Status; 381061da546Spatrick } 382061da546Spatrick break; 383061da546Spatrick 384061da546Spatrick default: 385061da546Spatrick done = true; 386061da546Spatrick break; 387061da546Spatrick } 388061da546Spatrick } 389061da546Spatrick 390061da546Spatrick if (m_index > start_index) { 391061da546Spatrick value = m_packet.substr(start_index, m_index - start_index); 392061da546Spatrick if (got_decimal_point) { 393061da546Spatrick if (exp_index != 0) { 394061da546Spatrick // We have an exponent, make sure we got exponent digits 395061da546Spatrick if (got_exp_digits) { 396061da546Spatrick return Token::Float; 397061da546Spatrick } else { 398061da546Spatrick error << "error: got exponent character but no exponent digits at " 399061da546Spatrick "offset in float value \"" 400061da546Spatrick << value.c_str() << "\""; 401061da546Spatrick value = error.str(); 402061da546Spatrick return Token::Status; 403061da546Spatrick } 404061da546Spatrick } else { 405061da546Spatrick // No exponent, but we need at least one decimal after the decimal 406061da546Spatrick // point 407061da546Spatrick if (got_frac_digits) { 408061da546Spatrick return Token::Float; 409061da546Spatrick } else { 410061da546Spatrick error << "error: no digits after decimal point \"" << value.c_str() 411061da546Spatrick << "\""; 412061da546Spatrick value = error.str(); 413061da546Spatrick return Token::Status; 414061da546Spatrick } 415061da546Spatrick } 416061da546Spatrick } else { 417061da546Spatrick // No decimal point 418061da546Spatrick if (got_int_digits) { 419061da546Spatrick // We need at least some integer digits to make an integer 420061da546Spatrick return Token::Integer; 421061da546Spatrick } else { 422061da546Spatrick error << "error: no digits negate sign \"" << value.c_str() << "\""; 423061da546Spatrick value = error.str(); 424061da546Spatrick return Token::Status; 425061da546Spatrick } 426061da546Spatrick } 427061da546Spatrick } else { 428061da546Spatrick error << "error: invalid number found at offset " << start_index; 429061da546Spatrick value = error.str(); 430061da546Spatrick return Token::Status; 431061da546Spatrick } 432061da546Spatrick } break; 433061da546Spatrick default: 434061da546Spatrick break; 435061da546Spatrick } 436061da546Spatrick error << "error: failed to parse token at offset " << start_index 437061da546Spatrick << " (around character '" << ch << "')"; 438061da546Spatrick value = error.str(); 439061da546Spatrick return Token::Status; 440061da546Spatrick } 441061da546Spatrick 442061da546Spatrick int JSONParser::GetEscapedChar(bool &was_escaped) { 443061da546Spatrick was_escaped = false; 444061da546Spatrick const char ch = GetChar(); 445061da546Spatrick if (ch == '\\') { 446061da546Spatrick was_escaped = true; 447061da546Spatrick const char ch2 = GetChar(); 448061da546Spatrick switch (ch2) { 449061da546Spatrick case '"': 450061da546Spatrick case '\\': 451061da546Spatrick case '/': 452061da546Spatrick default: 453061da546Spatrick break; 454061da546Spatrick 455061da546Spatrick case 'b': 456061da546Spatrick return '\b'; 457061da546Spatrick case 'f': 458061da546Spatrick return '\f'; 459061da546Spatrick case 'n': 460061da546Spatrick return '\n'; 461061da546Spatrick case 'r': 462061da546Spatrick return '\r'; 463061da546Spatrick case 't': 464061da546Spatrick return '\t'; 465061da546Spatrick case 'u': { 466061da546Spatrick const int hi_byte = DecodeHexU8(); 467061da546Spatrick const int lo_byte = DecodeHexU8(); 468061da546Spatrick if (hi_byte >= 0 && lo_byte >= 0) 469061da546Spatrick return hi_byte << 8 | lo_byte; 470061da546Spatrick return -1; 471061da546Spatrick } break; 472061da546Spatrick } 473061da546Spatrick return ch2; 474061da546Spatrick } 475061da546Spatrick return ch; 476061da546Spatrick } 477061da546Spatrick 478061da546Spatrick JSONValue::SP JSONParser::ParseJSONObject() { 479061da546Spatrick // The "JSONParser::Token::ObjectStart" token should have already been 480061da546Spatrick // consumed 481061da546Spatrick // by the time this function is called 482061da546Spatrick std::unique_ptr<JSONObject> dict_up(new JSONObject()); 483061da546Spatrick 484061da546Spatrick std::string value; 485061da546Spatrick std::string key; 486061da546Spatrick while (true) { 487061da546Spatrick JSONParser::Token token = GetToken(value); 488061da546Spatrick 489061da546Spatrick if (token == JSONParser::Token::String) { 490061da546Spatrick key.swap(value); 491061da546Spatrick token = GetToken(value); 492061da546Spatrick if (token == JSONParser::Token::Colon) { 493061da546Spatrick JSONValue::SP value_sp = ParseJSONValue(); 494061da546Spatrick if (value_sp) 495061da546Spatrick dict_up->SetObject(key, value_sp); 496061da546Spatrick else 497061da546Spatrick break; 498061da546Spatrick } 499061da546Spatrick } else if (token == JSONParser::Token::ObjectEnd) { 500061da546Spatrick return JSONValue::SP(dict_up.release()); 501061da546Spatrick } else if (token == JSONParser::Token::Comma) { 502061da546Spatrick continue; 503061da546Spatrick } else { 504061da546Spatrick break; 505061da546Spatrick } 506061da546Spatrick } 507061da546Spatrick return JSONValue::SP(); 508061da546Spatrick } 509061da546Spatrick 510061da546Spatrick JSONValue::SP JSONParser::ParseJSONArray() { 511061da546Spatrick // The "JSONParser::Token::ObjectStart" token should have already been 512061da546Spatrick // consumed 513061da546Spatrick // by the time this function is called 514061da546Spatrick std::unique_ptr<JSONArray> array_up(new JSONArray()); 515061da546Spatrick 516061da546Spatrick std::string value; 517061da546Spatrick std::string key; 518061da546Spatrick while (true) { 519061da546Spatrick JSONParser::Token token = GetToken(value); 520061da546Spatrick if (token == JSONParser::Token::ArrayEnd) 521061da546Spatrick return JSONValue::SP(array_up.release()); 522061da546Spatrick JSONValue::SP value_sp = ParseJSONValue(value, token); 523061da546Spatrick if (value_sp) 524061da546Spatrick array_up->AppendObject(value_sp); 525061da546Spatrick else 526061da546Spatrick break; 527061da546Spatrick 528061da546Spatrick token = GetToken(value); 529061da546Spatrick if (token == JSONParser::Token::Comma) { 530061da546Spatrick continue; 531061da546Spatrick } else if (token == JSONParser::Token::ArrayEnd) { 532061da546Spatrick return JSONValue::SP(array_up.release()); 533061da546Spatrick } else { 534061da546Spatrick break; 535061da546Spatrick } 536061da546Spatrick } 537061da546Spatrick return JSONValue::SP(); 538061da546Spatrick } 539061da546Spatrick 540061da546Spatrick JSONValue::SP JSONParser::ParseJSONValue() { 541061da546Spatrick std::string value; 542061da546Spatrick const JSONParser::Token token = GetToken(value); 543061da546Spatrick return ParseJSONValue(value, token); 544061da546Spatrick } 545061da546Spatrick 546061da546Spatrick JSONValue::SP JSONParser::ParseJSONValue(const std::string &value, 547061da546Spatrick const Token &token) { 548061da546Spatrick switch (token) { 549061da546Spatrick case JSONParser::Token::ObjectStart: 550061da546Spatrick return ParseJSONObject(); 551061da546Spatrick 552061da546Spatrick case JSONParser::Token::ArrayStart: 553061da546Spatrick return ParseJSONArray(); 554061da546Spatrick 555061da546Spatrick case JSONParser::Token::Integer: { 556061da546Spatrick if (value.front() == '-') { 557061da546Spatrick bool success = false; 558061da546Spatrick int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success); 559061da546Spatrick if (success) 560061da546Spatrick return JSONValue::SP(new JSONNumber(sval)); 561061da546Spatrick } else { 562061da546Spatrick bool success = false; 563061da546Spatrick uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); 564061da546Spatrick if (success) 565061da546Spatrick return JSONValue::SP(new JSONNumber(uval)); 566061da546Spatrick } 567061da546Spatrick } break; 568061da546Spatrick 569061da546Spatrick case JSONParser::Token::Float: { 570061da546Spatrick bool success = false; 571061da546Spatrick double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); 572061da546Spatrick if (success) 573061da546Spatrick return JSONValue::SP(new JSONNumber(val)); 574061da546Spatrick } break; 575061da546Spatrick 576061da546Spatrick case JSONParser::Token::String: 577061da546Spatrick return JSONValue::SP(new JSONString(value)); 578061da546Spatrick 579061da546Spatrick case JSONParser::Token::True: 580061da546Spatrick return JSONValue::SP(new JSONTrue()); 581061da546Spatrick 582061da546Spatrick case JSONParser::Token::False: 583061da546Spatrick return JSONValue::SP(new JSONFalse()); 584061da546Spatrick 585061da546Spatrick case JSONParser::Token::Null: 586061da546Spatrick return JSONValue::SP(new JSONNull()); 587061da546Spatrick 588061da546Spatrick default: 589061da546Spatrick break; 590061da546Spatrick } 591061da546Spatrick return JSONValue::SP(); 592061da546Spatrick } 593