1 //===--------------------- JSON.cpp -----------------------------*- 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 #include "lldb/Utility/JSON.h" 11 12 #include <limits.h> 13 #include "lldb/Core/StreamString.h" 14 #include "lldb/Host/StringConvert.h" 15 #include "llvm/Support/ErrorHandling.h" 16 17 using namespace lldb_private; 18 19 std::string 20 JSONString::json_string_quote_metachars (const std::string &s) 21 { 22 if (s.find('"') == std::string::npos) 23 return s; 24 25 std::string output; 26 const size_t s_size = s.size(); 27 const char *s_chars = s.c_str(); 28 for (size_t i = 0; i < s_size; i++) 29 { 30 unsigned char ch = *(s_chars + i); 31 if (ch == '"') 32 { 33 output.push_back ('\\'); 34 } 35 output.push_back (ch); 36 } 37 return output; 38 } 39 40 JSONString::JSONString () : 41 JSONValue(JSONValue::Kind::String), 42 m_data() 43 { 44 } 45 46 JSONString::JSONString (const char* s) : 47 JSONValue(JSONValue::Kind::String), 48 m_data(s ? s : "") 49 { 50 } 51 52 JSONString::JSONString (const std::string& s) : 53 JSONValue(JSONValue::Kind::String), 54 m_data(s) 55 { 56 } 57 58 void 59 JSONString::Write (Stream& s) 60 { 61 s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str()); 62 } 63 64 uint64_t 65 JSONNumber::GetAsUnsigned() const 66 { 67 switch (m_data_type) 68 { 69 case DataType::Unsigned: 70 return m_data.m_unsigned; 71 case DataType::Signed: 72 return (uint64_t)m_data.m_signed; 73 case DataType::Double: 74 return (uint64_t)m_data.m_double; 75 } 76 llvm_unreachable("Unhandled data type"); 77 } 78 79 int64_t 80 JSONNumber::GetAsSigned() const 81 { 82 switch (m_data_type) 83 { 84 case DataType::Unsigned: 85 return (int64_t)m_data.m_unsigned; 86 case DataType::Signed: 87 return m_data.m_signed; 88 case DataType::Double: 89 return (int64_t)m_data.m_double; 90 } 91 llvm_unreachable("Unhandled data type"); 92 } 93 94 double 95 JSONNumber::GetAsDouble() const 96 { 97 switch (m_data_type) 98 { 99 case DataType::Unsigned: 100 return (double)m_data.m_unsigned; 101 case DataType::Signed: 102 return (double)m_data.m_signed; 103 case DataType::Double: 104 return m_data.m_double; 105 } 106 llvm_unreachable("Unhandled data type"); 107 } 108 109 void 110 JSONNumber::Write (Stream& s) 111 { 112 switch (m_data_type) 113 { 114 case DataType::Unsigned: 115 s.Printf("%" PRIu64, m_data.m_unsigned); 116 break; 117 case DataType::Signed: 118 s.Printf("%" PRId64, m_data.m_signed); 119 break; 120 case DataType::Double: 121 s.Printf("%g", m_data.m_double); 122 break; 123 } 124 } 125 126 JSONTrue::JSONTrue () : 127 JSONValue(JSONValue::Kind::True) 128 { 129 } 130 131 void 132 JSONTrue::Write(Stream& s) 133 { 134 s.Printf("true"); 135 } 136 137 JSONFalse::JSONFalse () : 138 JSONValue(JSONValue::Kind::False) 139 { 140 } 141 142 void 143 JSONFalse::Write(Stream& s) 144 { 145 s.Printf("false"); 146 } 147 148 JSONNull::JSONNull () : 149 JSONValue(JSONValue::Kind::Null) 150 { 151 } 152 153 void 154 JSONNull::Write(Stream& s) 155 { 156 s.Printf("null"); 157 } 158 159 JSONObject::JSONObject () : 160 JSONValue(JSONValue::Kind::Object) 161 { 162 } 163 164 void 165 JSONObject::Write (Stream& s) 166 { 167 bool first = true; 168 s.PutChar('{'); 169 auto iter = m_elements.begin(), end = m_elements.end(); 170 for (;iter != end; iter++) 171 { 172 if (first) 173 first = false; 174 else 175 s.PutChar(','); 176 JSONString key(iter->first); 177 JSONValue::SP value(iter->second); 178 key.Write(s); 179 s.PutChar(':'); 180 value->Write(s); 181 } 182 s.PutChar('}'); 183 } 184 185 bool 186 JSONObject::SetObject (const std::string& key, 187 JSONValue::SP value) 188 { 189 if (key.empty() || nullptr == value.get()) 190 return false; 191 m_elements[key] = value; 192 return true; 193 } 194 195 JSONValue::SP 196 JSONObject::GetObject (const std::string& key) 197 { 198 auto iter = m_elements.find(key), end = m_elements.end(); 199 if (iter == end) 200 return JSONValue::SP(); 201 return iter->second; 202 } 203 204 JSONArray::JSONArray () : 205 JSONValue(JSONValue::Kind::Array) 206 { 207 } 208 209 void 210 JSONArray::Write (Stream& s) 211 { 212 bool first = true; 213 s.PutChar('['); 214 auto iter = m_elements.begin(), end = m_elements.end(); 215 for (;iter != end; iter++) 216 { 217 if (first) 218 first = false; 219 else 220 s.PutChar(','); 221 (*iter)->Write(s); 222 } 223 s.PutChar(']'); 224 } 225 226 bool 227 JSONArray::SetObject (Index i, 228 JSONValue::SP value) 229 { 230 if (value.get() == nullptr) 231 return false; 232 if (i < m_elements.size()) 233 { 234 m_elements[i] = value; 235 return true; 236 } 237 if (i == m_elements.size()) 238 { 239 m_elements.push_back(value); 240 return true; 241 } 242 return false; 243 } 244 245 bool 246 JSONArray::AppendObject (JSONValue::SP value) 247 { 248 if (value.get() == nullptr) 249 return false; 250 m_elements.push_back(value); 251 return true; 252 } 253 254 JSONValue::SP 255 JSONArray::GetObject (Index i) 256 { 257 if (i < m_elements.size()) 258 return m_elements[i]; 259 return JSONValue::SP(); 260 } 261 262 JSONArray::Size 263 JSONArray::GetNumElements () 264 { 265 return m_elements.size(); 266 } 267 268 269 JSONParser::JSONParser (const char *cstr) : 270 StringExtractor(cstr) 271 { 272 } 273 274 JSONParser::Token 275 JSONParser::GetToken (std::string &value) 276 { 277 StreamString error; 278 279 value.clear(); 280 SkipSpaces (); 281 const uint64_t start_index = m_index; 282 const char ch = GetChar(); 283 switch (ch) 284 { 285 case '{': return Token::ObjectStart; 286 case '}': return Token::ObjectEnd; 287 case '[': return Token::ArrayStart; 288 case ']': return Token::ArrayEnd; 289 case ',': return Token::Comma; 290 case ':': return Token::Colon; 291 case '\0': return Token::EndOfFile; 292 case 't': 293 if (GetChar() == 'r') 294 if (GetChar() == 'u') 295 if (GetChar() == 'e') 296 return Token::True; 297 break; 298 299 case 'f': 300 if (GetChar() == 'a') 301 if (GetChar() == 'l') 302 if (GetChar() == 's') 303 if (GetChar() == 'e') 304 return Token::False; 305 break; 306 307 case 'n': 308 if (GetChar() == 'u') 309 if (GetChar() == 'l') 310 if (GetChar() == 'l') 311 return Token::Null; 312 break; 313 314 case '"': 315 { 316 while (1) 317 { 318 bool was_escaped = false; 319 int escaped_ch = GetEscapedChar(was_escaped); 320 if (escaped_ch == -1) 321 { 322 error.Printf("error: an error occurred getting a character from offset %" PRIu64, start_index); 323 value = std::move(error.GetString()); 324 return Token::Error; 325 326 } 327 else 328 { 329 const bool is_end_quote = escaped_ch == '"'; 330 const bool is_null = escaped_ch == 0; 331 if (was_escaped || (!is_end_quote && !is_null)) 332 { 333 if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) 334 { 335 value.append(1, (char)escaped_ch); 336 } 337 else 338 { 339 error.Printf("error: wide character support is needed for unicode character 0x%4.4x at offset %" PRIu64, escaped_ch, start_index); 340 value = std::move(error.GetString()); 341 return Token::Error; 342 } 343 } 344 else if (is_end_quote) 345 { 346 return Token::String; 347 } 348 else if (is_null) 349 { 350 value = "error: missing end quote for string"; 351 return Token::Error; 352 } 353 } 354 } 355 } 356 break; 357 358 case '-': 359 case '0': 360 case '1': 361 case '2': 362 case '3': 363 case '4': 364 case '5': 365 case '6': 366 case '7': 367 case '8': 368 case '9': 369 { 370 bool done = false; 371 bool got_decimal_point = false; 372 uint64_t exp_index = 0; 373 bool got_int_digits = (ch >= '0') && (ch <= '9'); 374 bool got_frac_digits = false; 375 bool got_exp_digits = false; 376 while (!done) 377 { 378 const char next_ch = PeekChar(); 379 switch (next_ch) 380 { 381 case '0': 382 case '1': 383 case '2': 384 case '3': 385 case '4': 386 case '5': 387 case '6': 388 case '7': 389 case '8': 390 case '9': 391 if (exp_index != 0) 392 { 393 got_exp_digits = true; 394 } 395 else if (got_decimal_point) 396 { 397 got_frac_digits = true; 398 } 399 else 400 { 401 got_int_digits = true; 402 } 403 ++m_index; // Skip this character 404 break; 405 406 case '.': 407 if (got_decimal_point) 408 { 409 error.Printf("error: extra decimal point found at offset %" PRIu64, start_index); 410 value = std::move(error.GetString()); 411 return Token::Error; 412 } 413 else 414 { 415 got_decimal_point = true; 416 ++m_index; // Skip this character 417 } 418 break; 419 420 case 'e': 421 case 'E': 422 if (exp_index != 0) 423 { 424 error.Printf("error: extra exponent character found at offset %" PRIu64, start_index); 425 value = std::move(error.GetString()); 426 return Token::Error; 427 } 428 else 429 { 430 exp_index = m_index; 431 ++m_index; // Skip this character 432 } 433 break; 434 435 case '+': 436 case '-': 437 // The '+' and '-' can only come after an exponent character... 438 if (exp_index == m_index - 1) 439 { 440 ++m_index; // Skip the exponent sign character 441 } 442 else 443 { 444 error.Printf("error: unexpected %c character at offset %" PRIu64, next_ch, start_index); 445 value = std::move(error.GetString()); 446 return Token::Error; 447 } 448 break; 449 450 default: 451 done = true; 452 break; 453 } 454 } 455 456 if (m_index > start_index) 457 { 458 value = m_packet.substr(start_index, m_index - start_index); 459 if (got_decimal_point) 460 { 461 if (exp_index != 0) 462 { 463 // We have an exponent, make sure we got exponent digits 464 if (got_exp_digits) 465 { 466 return Token::Float; 467 } 468 else 469 { 470 error.Printf("error: got exponent character but no exponent digits at offset in float value \"%s\"", value.c_str()); 471 value = std::move(error.GetString()); 472 return Token::Error; 473 } 474 } 475 else 476 { 477 // No exponent, but we need at least one decimal after the decimal point 478 if (got_frac_digits) 479 { 480 return Token::Float; 481 } 482 else 483 { 484 error.Printf("error: no digits after decimal point \"%s\"", value.c_str()); 485 value = std::move(error.GetString()); 486 return Token::Error; 487 } 488 } 489 } 490 else 491 { 492 // No decimal point 493 if (got_int_digits) 494 { 495 // We need at least some integer digits to make an integer 496 return Token::Integer; 497 } 498 else 499 { 500 error.Printf("error: no digits negate sign \"%s\"", value.c_str()); 501 value = std::move(error.GetString()); 502 return Token::Error; 503 } 504 } 505 } 506 else 507 { 508 error.Printf("error: invalid number found at offset %" PRIu64, start_index); 509 value = std::move(error.GetString()); 510 return Token::Error; 511 } 512 } 513 break; 514 default: 515 break; 516 } 517 error.Printf("error: failed to parse token at offset %" PRIu64 " (around character '%c')", start_index, ch); 518 value = std::move(error.GetString()); 519 return Token::Error; 520 } 521 522 int 523 JSONParser::GetEscapedChar(bool &was_escaped) 524 { 525 was_escaped = false; 526 const char ch = GetChar(); 527 if (ch == '\\') 528 { 529 was_escaped = true; 530 const char ch2 = GetChar(); 531 switch (ch2) 532 { 533 case '"': 534 case '\\': 535 case '/': 536 default: 537 break; 538 539 case 'b': return '\b'; 540 case 'f': return '\f'; 541 case 'n': return '\n'; 542 case 'r': return '\r'; 543 case 't': return '\t'; 544 case 'u': 545 { 546 const int hi_byte = DecodeHexU8(); 547 const int lo_byte = DecodeHexU8(); 548 if (hi_byte >=0 && lo_byte >= 0) 549 return hi_byte << 8 | lo_byte; 550 return -1; 551 } 552 break; 553 } 554 return ch2; 555 } 556 return ch; 557 } 558 559 JSONValue::SP 560 JSONParser::ParseJSONObject () 561 { 562 // The "JSONParser::Token::ObjectStart" token should have already been consumed 563 // by the time this function is called 564 std::unique_ptr<JSONObject> dict_up(new JSONObject()); 565 566 std::string value; 567 std::string key; 568 while (1) 569 { 570 JSONParser::Token token = GetToken(value); 571 572 if (token == JSONParser::Token::String) 573 { 574 key.swap(value); 575 token = GetToken(value); 576 if (token == JSONParser::Token::Colon) 577 { 578 JSONValue::SP value_sp = ParseJSONValue(); 579 if (value_sp) 580 dict_up->SetObject(key, value_sp); 581 else 582 break; 583 } 584 } 585 else if (token == JSONParser::Token::ObjectEnd) 586 { 587 return JSONValue::SP(dict_up.release()); 588 } 589 else if (token == JSONParser::Token::Comma) 590 { 591 continue; 592 } 593 else 594 { 595 break; 596 } 597 } 598 return JSONValue::SP(); 599 } 600 601 JSONValue::SP 602 JSONParser::ParseJSONArray () 603 { 604 // The "JSONParser::Token::ObjectStart" token should have already been consumed 605 // by the time this function is called 606 std::unique_ptr<JSONArray> array_up(new JSONArray()); 607 608 std::string value; 609 std::string key; 610 while (1) 611 { 612 JSONValue::SP value_sp = ParseJSONValue(); 613 if (value_sp) 614 array_up->AppendObject(value_sp); 615 else 616 break; 617 618 JSONParser::Token token = GetToken(value); 619 if (token == JSONParser::Token::Comma) 620 { 621 continue; 622 } 623 else if (token == JSONParser::Token::ArrayEnd) 624 { 625 return JSONValue::SP(array_up.release()); 626 } 627 else 628 { 629 break; 630 } 631 } 632 return JSONValue::SP(); 633 } 634 635 JSONValue::SP 636 JSONParser::ParseJSONValue () 637 { 638 std::string value; 639 const JSONParser::Token token = GetToken(value); 640 switch (token) 641 { 642 case JSONParser::Token::ObjectStart: 643 return ParseJSONObject(); 644 645 case JSONParser::Token::ArrayStart: 646 return ParseJSONArray(); 647 648 case JSONParser::Token::Integer: 649 { 650 if (value.front() == '-') 651 { 652 bool success = false; 653 int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success); 654 if (success) 655 return JSONValue::SP(new JSONNumber(sval)); 656 } 657 else 658 { 659 bool success = false; 660 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); 661 if (success) 662 return JSONValue::SP(new JSONNumber(uval)); 663 } 664 } 665 break; 666 667 case JSONParser::Token::Float: 668 { 669 bool success = false; 670 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); 671 if (success) 672 return JSONValue::SP(new JSONNumber(val)); 673 } 674 break; 675 676 case JSONParser::Token::String: 677 return JSONValue::SP(new JSONString(value)); 678 679 case JSONParser::Token::True: 680 return JSONValue::SP(new JSONTrue()); 681 682 case JSONParser::Token::False: 683 return JSONValue::SP(new JSONFalse()); 684 685 case JSONParser::Token::Null: 686 return JSONValue::SP(new JSONNull()); 687 688 default: 689 break; 690 } 691 return JSONValue::SP(); 692 693 } 694