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 449 default: 450 done = true; 451 break; 452 } 453 } 454 455 if (m_index > start_index) 456 { 457 value = m_packet.substr(start_index, m_index - start_index); 458 if (got_decimal_point) 459 { 460 if (exp_index != 0) 461 { 462 // We have an exponent, make sure we got exponent digits 463 if (got_exp_digits) 464 { 465 return Token::Float; 466 } 467 else 468 { 469 error.Printf("error: got exponent character but no exponent digits at offset in float value \"%s\"", value.c_str()); 470 value = std::move(error.GetString()); 471 return Token::Error; 472 } 473 } 474 else 475 { 476 // No exponent, but we need at least one decimal after the decimal point 477 if (got_frac_digits) 478 { 479 return Token::Float; 480 } 481 else 482 { 483 error.Printf("error: no digits after decimal point \"%s\"", value.c_str()); 484 value = std::move(error.GetString()); 485 return Token::Error; 486 } 487 } 488 } 489 else 490 { 491 // No decimal point 492 if (got_int_digits) 493 { 494 // We need at least some integer digits to make an integer 495 return Token::Integer; 496 } 497 else 498 { 499 error.Printf("error: no digits negate sign \"%s\"", value.c_str()); 500 value = std::move(error.GetString()); 501 return Token::Error; 502 } 503 } 504 } 505 else 506 { 507 error.Printf("error: invalid number found at offset %" PRIu64, start_index); 508 value = std::move(error.GetString()); 509 return Token::Error; 510 } 511 } 512 break; 513 default: 514 break; 515 } 516 error.Printf("error: failed to parse token at offset %" PRIu64 " (around character '%c')", start_index, ch); 517 value = std::move(error.GetString()); 518 return Token::Error; 519 } 520 521 int 522 JSONParser::GetEscapedChar(bool &was_escaped) 523 { 524 was_escaped = false; 525 const char ch = GetChar(); 526 if (ch == '\\') 527 { 528 was_escaped = true; 529 const char ch2 = GetChar(); 530 switch (ch2) 531 { 532 case '"': 533 case '\\': 534 case '/': 535 default: 536 break; 537 538 case 'b': return '\b'; 539 case 'f': return '\f'; 540 case 'n': return '\n'; 541 case 'r': return '\r'; 542 case 't': return '\t'; 543 case 'u': 544 { 545 const int hi_byte = DecodeHexU8(); 546 const int lo_byte = DecodeHexU8(); 547 if (hi_byte >=0 && lo_byte >= 0) 548 return hi_byte << 8 | lo_byte; 549 return -1; 550 } 551 break; 552 } 553 return ch2; 554 } 555 return ch; 556 } 557 558 JSONValue::SP 559 JSONParser::ParseJSONObject () 560 { 561 // The "JSONParser::Token::ObjectStart" token should have already been consumed 562 // by the time this function is called 563 std::unique_ptr<JSONObject> dict_up(new JSONObject()); 564 565 std::string value; 566 std::string key; 567 while (1) 568 { 569 JSONParser::Token token = GetToken(value); 570 571 if (token == JSONParser::Token::String) 572 { 573 key.swap(value); 574 token = GetToken(value); 575 if (token == JSONParser::Token::Colon) 576 { 577 JSONValue::SP value_sp = ParseJSONValue(); 578 if (value_sp) 579 dict_up->SetObject(key, value_sp); 580 else 581 break; 582 } 583 } 584 else if (token == JSONParser::Token::ObjectEnd) 585 { 586 return JSONValue::SP(dict_up.release()); 587 } 588 else if (token == JSONParser::Token::Comma) 589 { 590 continue; 591 } 592 else 593 { 594 break; 595 } 596 } 597 return JSONValue::SP(); 598 } 599 600 JSONValue::SP 601 JSONParser::ParseJSONArray () 602 { 603 // The "JSONParser::Token::ObjectStart" token should have already been consumed 604 // by the time this function is called 605 std::unique_ptr<JSONArray> array_up(new JSONArray()); 606 607 std::string value; 608 std::string key; 609 while (1) 610 { 611 JSONValue::SP value_sp = ParseJSONValue(); 612 if (value_sp) 613 array_up->AppendObject(value_sp); 614 else 615 break; 616 617 JSONParser::Token token = GetToken(value); 618 if (token == JSONParser::Token::Comma) 619 { 620 continue; 621 } 622 else if (token == JSONParser::Token::ArrayEnd) 623 { 624 return JSONValue::SP(array_up.release()); 625 } 626 else 627 { 628 break; 629 } 630 } 631 return JSONValue::SP(); 632 } 633 634 JSONValue::SP 635 JSONParser::ParseJSONValue () 636 { 637 std::string value; 638 const JSONParser::Token token = GetToken(value); 639 switch (token) 640 { 641 case JSONParser::Token::ObjectStart: 642 return ParseJSONObject(); 643 644 case JSONParser::Token::ArrayStart: 645 return ParseJSONArray(); 646 647 case JSONParser::Token::Integer: 648 { 649 if (value.front() == '-') 650 { 651 bool success = false; 652 int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success); 653 if (success) 654 return JSONValue::SP(new JSONNumber(sval)); 655 } 656 else 657 { 658 bool success = false; 659 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success); 660 if (success) 661 return JSONValue::SP(new JSONNumber(uval)); 662 } 663 } 664 break; 665 666 case JSONParser::Token::Float: 667 { 668 bool success = false; 669 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success); 670 if (success) 671 return JSONValue::SP(new JSONNumber(val)); 672 } 673 break; 674 675 case JSONParser::Token::String: 676 return JSONValue::SP(new JSONString(value)); 677 678 case JSONParser::Token::True: 679 return JSONValue::SP(new JSONTrue()); 680 681 case JSONParser::Token::False: 682 return JSONValue::SP(new JSONFalse()); 683 684 case JSONParser::Token::Null: 685 return JSONValue::SP(new JSONNull()); 686 687 default: 688 break; 689 } 690 return JSONValue::SP(); 691 692 } 693