1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/). 2 /// It is intended to be used with #include "json/json.h" 3 4 // ////////////////////////////////////////////////////////////////////// 5 // Beginning of content of file: LICENSE 6 // ////////////////////////////////////////////////////////////////////// 7 8 /* 9 The JsonCpp library's source code, including accompanying documentation, 10 tests and demonstration applications, are licensed under the following 11 conditions... 12 13 The author (Baptiste Lepilleur) explicitly disclaims copyright in all 14 jurisdictions which recognize such a disclaimer. In such jurisdictions, 15 this software is released into the Public Domain. 16 17 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of 18 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is 19 released under the terms of the MIT License (see below). 20 21 In jurisdictions which recognize Public Domain property, the user of this 22 software may choose to accept it either as 1) Public Domain, 2) under the 23 conditions of the MIT License (see below), or 3) under the terms of dual 24 Public Domain/MIT License conditions described here, as they choose. 25 26 The MIT License is about as close to Public Domain as a license can get, and is 27 described in clear, concise terms at: 28 29 http://en.wikipedia.org/wiki/MIT_License 30 31 The full text of the MIT License follows: 32 33 ======================================================================== 34 Copyright (c) 2007-2010 Baptiste Lepilleur 35 36 Permission is hereby granted, free of charge, to any person 37 obtaining a copy of this software and associated documentation 38 files (the "Software"), to deal in the Software without 39 restriction, including without limitation the rights to use, copy, 40 modify, merge, publish, distribute, sublicense, and/or sell copies 41 of the Software, and to permit persons to whom the Software is 42 furnished to do so, subject to the following conditions: 43 44 The above copyright notice and this permission notice shall be 45 included in all copies or substantial portions of the Software. 46 47 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 48 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 49 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 50 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 51 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 52 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 53 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 54 SOFTWARE. 55 ======================================================================== 56 (END LICENSE TEXT) 57 58 The MIT license is compatible with both the GPL and commercial 59 software, affording one all of the rights of Public Domain with the 60 minor nuisance of being required to keep the above copyright notice 61 and license text in the source code. Note also that by accepting the 62 Public Domain "license" you can re-license your copy using whatever 63 license you like. 64 65 */ 66 67 // ////////////////////////////////////////////////////////////////////// 68 // End of content of file: LICENSE 69 // ////////////////////////////////////////////////////////////////////// 70 71 72 73 74 75 76 #include "third_party/jsoncpp/json.h" 77 78 #ifndef JSON_IS_AMALGAMATION 79 #error "Compile with -I PATH_TO_JSON_DIRECTORY" 80 #endif 81 82 83 // ////////////////////////////////////////////////////////////////////// 84 // Beginning of content of file: src/lib_json/json_tool.h 85 // ////////////////////////////////////////////////////////////////////// 86 87 // Copyright 2007-2010 Baptiste Lepilleur 88 // Distributed under MIT license, or public domain if desired and 89 // recognized in your jurisdiction. 90 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 91 92 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED 93 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED 94 95 /* This header provides common string manipulation support, such as UTF-8, 96 * portable conversion from/to string... 97 * 98 * It is an internal header that must not be exposed. 99 */ 100 101 namespace Json { 102 103 /// Converts a unicode code-point to UTF-8. 104 static inline std::string codePointToUTF8(unsigned int cp) { 105 std::string result; 106 107 // based on description from http://en.wikipedia.org/wiki/UTF-8 108 109 if (cp <= 0x7f) { 110 result.resize(1); 111 result[0] = static_cast<char>(cp); 112 } else if (cp <= 0x7FF) { 113 result.resize(2); 114 result[1] = static_cast<char>(0x80 | (0x3f & cp)); 115 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6))); 116 } else if (cp <= 0xFFFF) { 117 result.resize(3); 118 result[2] = static_cast<char>(0x80 | (0x3f & cp)); 119 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); 120 result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12))); 121 } else if (cp <= 0x10FFFF) { 122 result.resize(4); 123 result[3] = static_cast<char>(0x80 | (0x3f & cp)); 124 result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6))); 125 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12))); 126 result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18))); 127 } 128 129 return result; 130 } 131 132 /// Returns true if ch is a control character (in range [1,31]). 133 static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; } 134 135 enum { 136 /// Constant that specify the size of the buffer that must be passed to 137 /// uintToString. 138 uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1 139 }; 140 141 // Defines a char buffer for use with uintToString(). 142 typedef char UIntToStringBuffer[uintToStringBufferSize]; 143 144 /** Converts an unsigned integer to string. 145 * @param value Unsigned interger to convert to string 146 * @param current Input/Output string buffer. 147 * Must have at least uintToStringBufferSize chars free. 148 */ 149 static inline void uintToString(LargestUInt value, char*& current) { 150 *--current = 0; 151 do { 152 *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0')); 153 value /= 10; 154 } while (value != 0); 155 } 156 157 /** Change ',' to '.' everywhere in buffer. 158 * 159 * We had a sophisticated way, but it did not work in WinCE. 160 * @see https://github.com/open-source-parsers/jsoncpp/pull/9 161 */ 162 static inline void fixNumericLocale(char* begin, char* end) { 163 while (begin < end) { 164 if (*begin == ',') { 165 *begin = '.'; 166 } 167 ++begin; 168 } 169 } 170 171 } // namespace Json { 172 173 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED 174 175 // ////////////////////////////////////////////////////////////////////// 176 // End of content of file: src/lib_json/json_tool.h 177 // ////////////////////////////////////////////////////////////////////// 178 179 180 181 182 183 184 // ////////////////////////////////////////////////////////////////////// 185 // Beginning of content of file: src/lib_json/json_reader.cpp 186 // ////////////////////////////////////////////////////////////////////// 187 188 // Copyright 2007-2011 Baptiste Lepilleur 189 // Distributed under MIT license, or public domain if desired and 190 // recognized in your jurisdiction. 191 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 192 193 #if !defined(JSON_IS_AMALGAMATION) 194 #include <json/assertions.h> 195 #include <json/reader.h> 196 #include <json/value.h> 197 #include "json_tool.h" 198 #endif // if !defined(JSON_IS_AMALGAMATION) 199 #include <utility> 200 #include <cstdio> 201 #include <cassert> 202 #include <cstring> 203 #include <istream> 204 #include <sstream> 205 #include <memory> 206 #include <set> 207 #include <limits> 208 209 #if defined(_MSC_VER) 210 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 211 #define snprintf sprintf_s 212 #elif _MSC_VER >= 1900 // VC++ 14.0 and above 213 #define snprintf std::snprintf 214 #else 215 #define snprintf _snprintf 216 #endif 217 #elif defined(__ANDROID__) || defined(__QNXNTO__) 218 #define snprintf snprintf 219 #elif __cplusplus >= 201103L 220 #define snprintf std::snprintf 221 #endif 222 223 #if defined(__QNXNTO__) 224 #define sscanf std::sscanf 225 #endif 226 227 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 228 // Disable warning about strdup being deprecated. 229 #pragma warning(disable : 4996) 230 #endif 231 232 static int const stackLimit_g = 1000; 233 static int stackDepth_g = 0; // see readValue() 234 235 namespace Json { 236 237 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 238 typedef std::unique_ptr<CharReader> CharReaderPtr; 239 #else 240 typedef std::auto_ptr<CharReader> CharReaderPtr; 241 #endif 242 243 // Implementation of class Features 244 // //////////////////////////////// 245 246 Features::Features() 247 : allowComments_(true), strictRoot_(false), 248 allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {} 249 250 Features Features::all() { return Features(); } 251 252 Features Features::strictMode() { 253 Features features; 254 features.allowComments_ = false; 255 features.strictRoot_ = true; 256 features.allowDroppedNullPlaceholders_ = false; 257 features.allowNumericKeys_ = false; 258 return features; 259 } 260 261 // Implementation of class Reader 262 // //////////////////////////////// 263 264 static bool containsNewLine(Reader::Location begin, Reader::Location end) { 265 for (; begin < end; ++begin) 266 if (*begin == '\n' || *begin == '\r') 267 return true; 268 return false; 269 } 270 271 // Class Reader 272 // ////////////////////////////////////////////////////////////////// 273 274 Reader::Reader() 275 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 276 lastValue_(), commentsBefore_(), features_(Features::all()), 277 collectComments_() {} 278 279 Reader::Reader(const Features& features) 280 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 281 lastValue_(), commentsBefore_(), features_(features), collectComments_() { 282 } 283 284 bool 285 Reader::parse(const std::string& document, Value& root, bool collectComments) { 286 document_ = document; 287 const char* begin = document_.c_str(); 288 const char* end = begin + document_.length(); 289 return parse(begin, end, root, collectComments); 290 } 291 292 bool Reader::parse(std::istream& sin, Value& root, bool collectComments) { 293 // std::istream_iterator<char> begin(sin); 294 // std::istream_iterator<char> end; 295 // Those would allow streamed input from a file, if parse() were a 296 // template function. 297 298 // Since std::string is reference-counted, this at least does not 299 // create an extra copy. 300 std::string doc; 301 std::getline(sin, doc, (char)EOF); 302 return parse(doc, root, collectComments); 303 } 304 305 bool Reader::parse(const char* beginDoc, 306 const char* endDoc, 307 Value& root, 308 bool collectComments) { 309 if (!features_.allowComments_) { 310 collectComments = false; 311 } 312 313 begin_ = beginDoc; 314 end_ = endDoc; 315 collectComments_ = collectComments; 316 current_ = begin_; 317 lastValueEnd_ = 0; 318 lastValue_ = 0; 319 commentsBefore_ = ""; 320 errors_.clear(); 321 while (!nodes_.empty()) 322 nodes_.pop(); 323 nodes_.push(&root); 324 325 stackDepth_g = 0; // Yes, this is bad coding, but options are limited. 326 bool successful = readValue(); 327 Token token; 328 skipCommentTokens(token); 329 if (collectComments_ && !commentsBefore_.empty()) 330 root.setComment(commentsBefore_, commentAfter); 331 if (features_.strictRoot_) { 332 if (!root.isArray() && !root.isObject()) { 333 // Set error location to start of doc, ideally should be first token found 334 // in doc 335 token.type_ = tokenError; 336 token.start_ = beginDoc; 337 token.end_ = endDoc; 338 addError( 339 "A valid JSON document must be either an array or an object value.", 340 token); 341 return false; 342 } 343 } 344 return successful; 345 } 346 347 bool Reader::readValue() { 348 // This is a non-reentrant way to support a stackLimit. Terrible! 349 // But this deprecated class has a security problem: Bad input can 350 // cause a seg-fault. This seems like a fair, binary-compatible way 351 // to prevent the problem. 352 if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue()."); 353 ++stackDepth_g; 354 355 Token token; 356 skipCommentTokens(token); 357 bool successful = true; 358 359 if (collectComments_ && !commentsBefore_.empty()) { 360 currentValue().setComment(commentsBefore_, commentBefore); 361 commentsBefore_ = ""; 362 } 363 364 switch (token.type_) { 365 case tokenObjectBegin: 366 successful = readObject(token); 367 currentValue().setOffsetLimit(current_ - begin_); 368 break; 369 case tokenArrayBegin: 370 successful = readArray(token); 371 currentValue().setOffsetLimit(current_ - begin_); 372 break; 373 case tokenNumber: 374 successful = decodeNumber(token); 375 break; 376 case tokenString: 377 successful = decodeString(token); 378 break; 379 case tokenTrue: 380 { 381 Value v(true); 382 currentValue().swapPayload(v); 383 currentValue().setOffsetStart(token.start_ - begin_); 384 currentValue().setOffsetLimit(token.end_ - begin_); 385 } 386 break; 387 case tokenFalse: 388 { 389 Value v(false); 390 currentValue().swapPayload(v); 391 currentValue().setOffsetStart(token.start_ - begin_); 392 currentValue().setOffsetLimit(token.end_ - begin_); 393 } 394 break; 395 case tokenNull: 396 { 397 Value v; 398 currentValue().swapPayload(v); 399 currentValue().setOffsetStart(token.start_ - begin_); 400 currentValue().setOffsetLimit(token.end_ - begin_); 401 } 402 break; 403 case tokenArraySeparator: 404 case tokenObjectEnd: 405 case tokenArrayEnd: 406 if (features_.allowDroppedNullPlaceholders_) { 407 // "Un-read" the current token and mark the current value as a null 408 // token. 409 current_--; 410 Value v; 411 currentValue().swapPayload(v); 412 currentValue().setOffsetStart(current_ - begin_ - 1); 413 currentValue().setOffsetLimit(current_ - begin_); 414 break; 415 } // Else, fall through... 416 default: 417 currentValue().setOffsetStart(token.start_ - begin_); 418 currentValue().setOffsetLimit(token.end_ - begin_); 419 return addError("Syntax error: value, object or array expected.", token); 420 } 421 422 if (collectComments_) { 423 lastValueEnd_ = current_; 424 lastValue_ = ¤tValue(); 425 } 426 427 --stackDepth_g; 428 return successful; 429 } 430 431 void Reader::skipCommentTokens(Token& token) { 432 if (features_.allowComments_) { 433 do { 434 readToken(token); 435 } while (token.type_ == tokenComment); 436 } else { 437 readToken(token); 438 } 439 } 440 441 bool Reader::readToken(Token& token) { 442 skipSpaces(); 443 token.start_ = current_; 444 Char c = getNextChar(); 445 bool ok = true; 446 switch (c) { 447 case '{': 448 token.type_ = tokenObjectBegin; 449 break; 450 case '}': 451 token.type_ = tokenObjectEnd; 452 break; 453 case '[': 454 token.type_ = tokenArrayBegin; 455 break; 456 case ']': 457 token.type_ = tokenArrayEnd; 458 break; 459 case '"': 460 token.type_ = tokenString; 461 ok = readString(); 462 break; 463 case '/': 464 token.type_ = tokenComment; 465 ok = readComment(); 466 break; 467 case '0': 468 case '1': 469 case '2': 470 case '3': 471 case '4': 472 case '5': 473 case '6': 474 case '7': 475 case '8': 476 case '9': 477 case '-': 478 token.type_ = tokenNumber; 479 readNumber(); 480 break; 481 case 't': 482 token.type_ = tokenTrue; 483 ok = match("rue", 3); 484 break; 485 case 'f': 486 token.type_ = tokenFalse; 487 ok = match("alse", 4); 488 break; 489 case 'n': 490 token.type_ = tokenNull; 491 ok = match("ull", 3); 492 break; 493 case ',': 494 token.type_ = tokenArraySeparator; 495 break; 496 case ':': 497 token.type_ = tokenMemberSeparator; 498 break; 499 case 0: 500 token.type_ = tokenEndOfStream; 501 break; 502 default: 503 ok = false; 504 break; 505 } 506 if (!ok) 507 token.type_ = tokenError; 508 token.end_ = current_; 509 return true; 510 } 511 512 void Reader::skipSpaces() { 513 while (current_ != end_) { 514 Char c = *current_; 515 if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 516 ++current_; 517 else 518 break; 519 } 520 } 521 522 bool Reader::match(Location pattern, int patternLength) { 523 if (end_ - current_ < patternLength) 524 return false; 525 int index = patternLength; 526 while (index--) 527 if (current_[index] != pattern[index]) 528 return false; 529 current_ += patternLength; 530 return true; 531 } 532 533 bool Reader::readComment() { 534 Location commentBegin = current_ - 1; 535 Char c = getNextChar(); 536 bool successful = false; 537 if (c == '*') 538 successful = readCStyleComment(); 539 else if (c == '/') 540 successful = readCppStyleComment(); 541 if (!successful) 542 return false; 543 544 if (collectComments_) { 545 CommentPlacement placement = commentBefore; 546 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { 547 if (c != '*' || !containsNewLine(commentBegin, current_)) 548 placement = commentAfterOnSameLine; 549 } 550 551 addComment(commentBegin, current_, placement); 552 } 553 return true; 554 } 555 556 static std::string normalizeEOL(Reader::Location begin, Reader::Location end) { 557 std::string normalized; 558 normalized.reserve(end - begin); 559 Reader::Location current = begin; 560 while (current != end) { 561 char c = *current++; 562 if (c == '\r') { 563 if (current != end && *current == '\n') 564 // convert dos EOL 565 ++current; 566 // convert Mac EOL 567 normalized += '\n'; 568 } else { 569 normalized += c; 570 } 571 } 572 return normalized; 573 } 574 575 void 576 Reader::addComment(Location begin, Location end, CommentPlacement placement) { 577 assert(collectComments_); 578 const std::string& normalized = normalizeEOL(begin, end); 579 if (placement == commentAfterOnSameLine) { 580 assert(lastValue_ != 0); 581 lastValue_->setComment(normalized, placement); 582 } else { 583 commentsBefore_ += normalized; 584 } 585 } 586 587 bool Reader::readCStyleComment() { 588 while (current_ != end_) { 589 Char c = getNextChar(); 590 if (c == '*' && *current_ == '/') 591 break; 592 } 593 return getNextChar() == '/'; 594 } 595 596 bool Reader::readCppStyleComment() { 597 while (current_ != end_) { 598 Char c = getNextChar(); 599 if (c == '\n') 600 break; 601 if (c == '\r') { 602 // Consume DOS EOL. It will be normalized in addComment. 603 if (current_ != end_ && *current_ == '\n') 604 getNextChar(); 605 // Break on Moc OS 9 EOL. 606 break; 607 } 608 } 609 return true; 610 } 611 612 void Reader::readNumber() { 613 const char *p = current_; 614 char c = '0'; // stopgap for already consumed character 615 // integral part 616 while (c >= '0' && c <= '9') 617 c = (current_ = p) < end_ ? *p++ : 0; 618 // fractional part 619 if (c == '.') { 620 c = (current_ = p) < end_ ? *p++ : 0; 621 while (c >= '0' && c <= '9') 622 c = (current_ = p) < end_ ? *p++ : 0; 623 } 624 // exponential part 625 if (c == 'e' || c == 'E') { 626 c = (current_ = p) < end_ ? *p++ : 0; 627 if (c == '+' || c == '-') 628 c = (current_ = p) < end_ ? *p++ : 0; 629 while (c >= '0' && c <= '9') 630 c = (current_ = p) < end_ ? *p++ : 0; 631 } 632 } 633 634 bool Reader::readString() { 635 Char c = 0; 636 while (current_ != end_) { 637 c = getNextChar(); 638 if (c == '\\') 639 getNextChar(); 640 else if (c == '"') 641 break; 642 } 643 return c == '"'; 644 } 645 646 bool Reader::readObject(Token& tokenStart) { 647 Token tokenName; 648 std::string name; 649 Value init(objectValue); 650 currentValue().swapPayload(init); 651 currentValue().setOffsetStart(tokenStart.start_ - begin_); 652 while (readToken(tokenName)) { 653 bool initialTokenOk = true; 654 while (tokenName.type_ == tokenComment && initialTokenOk) 655 initialTokenOk = readToken(tokenName); 656 if (!initialTokenOk) 657 break; 658 if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object 659 return true; 660 name = ""; 661 if (tokenName.type_ == tokenString) { 662 if (!decodeString(tokenName, name)) 663 return recoverFromError(tokenObjectEnd); 664 } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { 665 Value numberName; 666 if (!decodeNumber(tokenName, numberName)) 667 return recoverFromError(tokenObjectEnd); 668 name = numberName.asString(); 669 } else { 670 break; 671 } 672 673 Token colon; 674 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { 675 return addErrorAndRecover( 676 "Missing ':' after object member name", colon, tokenObjectEnd); 677 } 678 Value& value = currentValue()[name]; 679 nodes_.push(&value); 680 bool ok = readValue(); 681 nodes_.pop(); 682 if (!ok) // error already set 683 return recoverFromError(tokenObjectEnd); 684 685 Token comma; 686 if (!readToken(comma) || 687 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && 688 comma.type_ != tokenComment)) { 689 return addErrorAndRecover( 690 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); 691 } 692 bool finalizeTokenOk = true; 693 while (comma.type_ == tokenComment && finalizeTokenOk) 694 finalizeTokenOk = readToken(comma); 695 if (comma.type_ == tokenObjectEnd) 696 return true; 697 } 698 return addErrorAndRecover( 699 "Missing '}' or object member name", tokenName, tokenObjectEnd); 700 } 701 702 bool Reader::readArray(Token& tokenStart) { 703 Value init(arrayValue); 704 currentValue().swapPayload(init); 705 currentValue().setOffsetStart(tokenStart.start_ - begin_); 706 skipSpaces(); 707 if (*current_ == ']') // empty array 708 { 709 Token endArray; 710 readToken(endArray); 711 return true; 712 } 713 int index = 0; 714 for (;;) { 715 Value& value = currentValue()[index++]; 716 nodes_.push(&value); 717 bool ok = readValue(); 718 nodes_.pop(); 719 if (!ok) // error already set 720 return recoverFromError(tokenArrayEnd); 721 722 Token token; 723 // Accept Comment after last item in the array. 724 ok = readToken(token); 725 while (token.type_ == tokenComment && ok) { 726 ok = readToken(token); 727 } 728 bool badTokenType = 729 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); 730 if (!ok || badTokenType) { 731 return addErrorAndRecover( 732 "Missing ',' or ']' in array declaration", token, tokenArrayEnd); 733 } 734 if (token.type_ == tokenArrayEnd) 735 break; 736 } 737 return true; 738 } 739 740 bool Reader::decodeNumber(Token& token) { 741 Value decoded; 742 if (!decodeNumber(token, decoded)) 743 return false; 744 currentValue().swapPayload(decoded); 745 currentValue().setOffsetStart(token.start_ - begin_); 746 currentValue().setOffsetLimit(token.end_ - begin_); 747 return true; 748 } 749 750 bool Reader::decodeNumber(Token& token, Value& decoded) { 751 // Attempts to parse the number as an integer. If the number is 752 // larger than the maximum supported value of an integer then 753 // we decode the number as a double. 754 Location current = token.start_; 755 bool isNegative = *current == '-'; 756 if (isNegative) 757 ++current; 758 // TODO: Help the compiler do the div and mod at compile time or get rid of them. 759 Value::LargestUInt maxIntegerValue = 760 isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 761 : Value::maxLargestUInt; 762 Value::LargestUInt threshold = maxIntegerValue / 10; 763 Value::LargestUInt value = 0; 764 while (current < token.end_) { 765 Char c = *current++; 766 if (c < '0' || c > '9') 767 return decodeDouble(token, decoded); 768 Value::UInt digit(c - '0'); 769 if (value >= threshold) { 770 // We've hit or exceeded the max value divided by 10 (rounded down). If 771 // a) we've only just touched the limit, b) this is the last digit, and 772 // c) it's small enough to fit in that rounding delta, we're okay. 773 // Otherwise treat this number as a double to avoid overflow. 774 if (value > threshold || current != token.end_ || 775 digit > maxIntegerValue % 10) { 776 return decodeDouble(token, decoded); 777 } 778 } 779 value = value * 10 + digit; 780 } 781 if (isNegative && value == maxIntegerValue) 782 decoded = Value::minLargestInt; 783 else if (isNegative) 784 decoded = -Value::LargestInt(value); 785 else if (value <= Value::LargestUInt(Value::maxInt)) 786 decoded = Value::LargestInt(value); 787 else 788 decoded = value; 789 return true; 790 } 791 792 bool Reader::decodeDouble(Token& token) { 793 Value decoded; 794 if (!decodeDouble(token, decoded)) 795 return false; 796 currentValue().swapPayload(decoded); 797 currentValue().setOffsetStart(token.start_ - begin_); 798 currentValue().setOffsetLimit(token.end_ - begin_); 799 return true; 800 } 801 802 bool Reader::decodeDouble(Token& token, Value& decoded) { 803 double value = 0; 804 std::string buffer(token.start_, token.end_); 805 std::istringstream is(buffer); 806 if (!(is >> value)) 807 return addError("'" + std::string(token.start_, token.end_) + 808 "' is not a number.", 809 token); 810 decoded = value; 811 return true; 812 } 813 814 bool Reader::decodeString(Token& token) { 815 std::string decoded_string; 816 if (!decodeString(token, decoded_string)) 817 return false; 818 Value decoded(decoded_string); 819 currentValue().swapPayload(decoded); 820 currentValue().setOffsetStart(token.start_ - begin_); 821 currentValue().setOffsetLimit(token.end_ - begin_); 822 return true; 823 } 824 825 bool Reader::decodeString(Token& token, std::string& decoded) { 826 decoded.reserve(token.end_ - token.start_ - 2); 827 Location current = token.start_ + 1; // skip '"' 828 Location end = token.end_ - 1; // do not include '"' 829 while (current != end) { 830 Char c = *current++; 831 if (c == '"') 832 break; 833 else if (c == '\\') { 834 if (current == end) 835 return addError("Empty escape sequence in string", token, current); 836 Char escape = *current++; 837 switch (escape) { 838 case '"': 839 decoded += '"'; 840 break; 841 case '/': 842 decoded += '/'; 843 break; 844 case '\\': 845 decoded += '\\'; 846 break; 847 case 'b': 848 decoded += '\b'; 849 break; 850 case 'f': 851 decoded += '\f'; 852 break; 853 case 'n': 854 decoded += '\n'; 855 break; 856 case 'r': 857 decoded += '\r'; 858 break; 859 case 't': 860 decoded += '\t'; 861 break; 862 case 'u': { 863 unsigned int unicode; 864 if (!decodeUnicodeCodePoint(token, current, end, unicode)) 865 return false; 866 decoded += codePointToUTF8(unicode); 867 } break; 868 default: 869 return addError("Bad escape sequence in string", token, current); 870 } 871 } else { 872 decoded += c; 873 } 874 } 875 return true; 876 } 877 878 bool Reader::decodeUnicodeCodePoint(Token& token, 879 Location& current, 880 Location end, 881 unsigned int& unicode) { 882 883 if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) 884 return false; 885 if (unicode >= 0xD800 && unicode <= 0xDBFF) { 886 // surrogate pairs 887 if (end - current < 6) 888 return addError( 889 "additional six characters expected to parse unicode surrogate pair.", 890 token, 891 current); 892 unsigned int surrogatePair; 893 if (*(current++) == '\\' && *(current++) == 'u') { 894 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { 895 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 896 } else 897 return false; 898 } else 899 return addError("expecting another \\u token to begin the second half of " 900 "a unicode surrogate pair", 901 token, 902 current); 903 } 904 return true; 905 } 906 907 bool Reader::decodeUnicodeEscapeSequence(Token& token, 908 Location& current, 909 Location end, 910 unsigned int& unicode) { 911 if (end - current < 4) 912 return addError( 913 "Bad unicode escape sequence in string: four digits expected.", 914 token, 915 current); 916 unicode = 0; 917 for (int index = 0; index < 4; ++index) { 918 Char c = *current++; 919 unicode *= 16; 920 if (c >= '0' && c <= '9') 921 unicode += c - '0'; 922 else if (c >= 'a' && c <= 'f') 923 unicode += c - 'a' + 10; 924 else if (c >= 'A' && c <= 'F') 925 unicode += c - 'A' + 10; 926 else 927 return addError( 928 "Bad unicode escape sequence in string: hexadecimal digit expected.", 929 token, 930 current); 931 } 932 return true; 933 } 934 935 bool 936 Reader::addError(const std::string& message, Token& token, Location extra) { 937 ErrorInfo info; 938 info.token_ = token; 939 info.message_ = message; 940 info.extra_ = extra; 941 errors_.push_back(info); 942 return false; 943 } 944 945 bool Reader::recoverFromError(TokenType skipUntilToken) { 946 int errorCount = int(errors_.size()); 947 Token skip; 948 for (;;) { 949 if (!readToken(skip)) 950 errors_.resize(errorCount); // discard errors caused by recovery 951 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) 952 break; 953 } 954 errors_.resize(errorCount); 955 return false; 956 } 957 958 bool Reader::addErrorAndRecover(const std::string& message, 959 Token& token, 960 TokenType skipUntilToken) { 961 addError(message, token); 962 return recoverFromError(skipUntilToken); 963 } 964 965 Value& Reader::currentValue() { return *(nodes_.top()); } 966 967 Reader::Char Reader::getNextChar() { 968 if (current_ == end_) 969 return 0; 970 return *current_++; 971 } 972 973 void Reader::getLocationLineAndColumn(Location location, 974 int& line, 975 int& column) const { 976 Location current = begin_; 977 Location lastLineStart = current; 978 line = 0; 979 while (current < location && current != end_) { 980 Char c = *current++; 981 if (c == '\r') { 982 if (*current == '\n') 983 ++current; 984 lastLineStart = current; 985 ++line; 986 } else if (c == '\n') { 987 lastLineStart = current; 988 ++line; 989 } 990 } 991 // column & line start at 1 992 column = int(location - lastLineStart) + 1; 993 ++line; 994 } 995 996 std::string Reader::getLocationLineAndColumn(Location location) const { 997 int line, column; 998 getLocationLineAndColumn(location, line, column); 999 char buffer[18 + 16 + 16 + 1]; 1000 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 1001 return buffer; 1002 } 1003 1004 // Deprecated. Preserved for backward compatibility 1005 std::string Reader::getFormatedErrorMessages() const { 1006 return getFormattedErrorMessages(); 1007 } 1008 1009 std::string Reader::getFormattedErrorMessages() const { 1010 std::string formattedMessage; 1011 for (Errors::const_iterator itError = errors_.begin(); 1012 itError != errors_.end(); 1013 ++itError) { 1014 const ErrorInfo& error = *itError; 1015 formattedMessage += 1016 "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; 1017 formattedMessage += " " + error.message_ + "\n"; 1018 if (error.extra_) 1019 formattedMessage += 1020 "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; 1021 } 1022 return formattedMessage; 1023 } 1024 1025 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const { 1026 std::vector<Reader::StructuredError> allErrors; 1027 for (Errors::const_iterator itError = errors_.begin(); 1028 itError != errors_.end(); 1029 ++itError) { 1030 const ErrorInfo& error = *itError; 1031 Reader::StructuredError structured; 1032 structured.offset_start = error.token_.start_ - begin_; 1033 structured.offset_limit = error.token_.end_ - begin_; 1034 structured.message = error.message_; 1035 allErrors.push_back(structured); 1036 } 1037 return allErrors; 1038 } 1039 1040 bool Reader::pushError(const Value& value, const std::string& message) { 1041 size_t length = end_ - begin_; 1042 if(value.getOffsetStart() > length 1043 || value.getOffsetLimit() > length) 1044 return false; 1045 Token token; 1046 token.type_ = tokenError; 1047 token.start_ = begin_ + value.getOffsetStart(); 1048 token.end_ = end_ + value.getOffsetLimit(); 1049 ErrorInfo info; 1050 info.token_ = token; 1051 info.message_ = message; 1052 info.extra_ = 0; 1053 errors_.push_back(info); 1054 return true; 1055 } 1056 1057 bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) { 1058 size_t length = end_ - begin_; 1059 if(value.getOffsetStart() > length 1060 || value.getOffsetLimit() > length 1061 || extra.getOffsetLimit() > length) 1062 return false; 1063 Token token; 1064 token.type_ = tokenError; 1065 token.start_ = begin_ + value.getOffsetStart(); 1066 token.end_ = begin_ + value.getOffsetLimit(); 1067 ErrorInfo info; 1068 info.token_ = token; 1069 info.message_ = message; 1070 info.extra_ = begin_ + extra.getOffsetStart(); 1071 errors_.push_back(info); 1072 return true; 1073 } 1074 1075 bool Reader::good() const { 1076 return !errors_.size(); 1077 } 1078 1079 // exact copy of Features 1080 class OurFeatures { 1081 public: 1082 static OurFeatures all(); 1083 bool allowComments_; 1084 bool strictRoot_; 1085 bool allowDroppedNullPlaceholders_; 1086 bool allowNumericKeys_; 1087 bool allowSingleQuotes_; 1088 bool failIfExtra_; 1089 bool rejectDupKeys_; 1090 bool allowSpecialFloats_; 1091 int stackLimit_; 1092 }; // OurFeatures 1093 1094 // exact copy of Implementation of class Features 1095 // //////////////////////////////// 1096 1097 OurFeatures OurFeatures::all() { return OurFeatures(); } 1098 1099 // Implementation of class Reader 1100 // //////////////////////////////// 1101 1102 // exact copy of Reader, renamed to OurReader 1103 class OurReader { 1104 public: 1105 typedef char Char; 1106 typedef const Char* Location; 1107 struct StructuredError { 1108 size_t offset_start; 1109 size_t offset_limit; 1110 std::string message; 1111 }; 1112 1113 OurReader(OurFeatures const& features); 1114 bool parse(const char* beginDoc, 1115 const char* endDoc, 1116 Value& root, 1117 bool collectComments = true); 1118 std::string getFormattedErrorMessages() const; 1119 std::vector<StructuredError> getStructuredErrors() const; 1120 bool pushError(const Value& value, const std::string& message); 1121 bool pushError(const Value& value, const std::string& message, const Value& extra); 1122 bool good() const; 1123 1124 private: 1125 OurReader(OurReader const&); // no impl 1126 void operator=(OurReader const&); // no impl 1127 1128 enum TokenType { 1129 tokenEndOfStream = 0, 1130 tokenObjectBegin, 1131 tokenObjectEnd, 1132 tokenArrayBegin, 1133 tokenArrayEnd, 1134 tokenString, 1135 tokenNumber, 1136 tokenTrue, 1137 tokenFalse, 1138 tokenNull, 1139 tokenNaN, 1140 tokenPosInf, 1141 tokenNegInf, 1142 tokenArraySeparator, 1143 tokenMemberSeparator, 1144 tokenComment, 1145 tokenError 1146 }; 1147 1148 class Token { 1149 public: 1150 TokenType type_; 1151 Location start_; 1152 Location end_; 1153 }; 1154 1155 class ErrorInfo { 1156 public: 1157 Token token_; 1158 std::string message_; 1159 Location extra_; 1160 }; 1161 1162 typedef std::deque<ErrorInfo> Errors; 1163 1164 bool readToken(Token& token); 1165 void skipSpaces(); 1166 bool match(Location pattern, int patternLength); 1167 bool readComment(); 1168 bool readCStyleComment(); 1169 bool readCppStyleComment(); 1170 bool readString(); 1171 bool readStringSingleQuote(); 1172 bool readNumber(bool checkInf); 1173 bool readValue(); 1174 bool readObject(Token& token); 1175 bool readArray(Token& token); 1176 bool decodeNumber(Token& token); 1177 bool decodeNumber(Token& token, Value& decoded); 1178 bool decodeString(Token& token); 1179 bool decodeString(Token& token, std::string& decoded); 1180 bool decodeDouble(Token& token); 1181 bool decodeDouble(Token& token, Value& decoded); 1182 bool decodeUnicodeCodePoint(Token& token, 1183 Location& current, 1184 Location end, 1185 unsigned int& unicode); 1186 bool decodeUnicodeEscapeSequence(Token& token, 1187 Location& current, 1188 Location end, 1189 unsigned int& unicode); 1190 bool addError(const std::string& message, Token& token, Location extra = 0); 1191 bool recoverFromError(TokenType skipUntilToken); 1192 bool addErrorAndRecover(const std::string& message, 1193 Token& token, 1194 TokenType skipUntilToken); 1195 void skipUntilSpace(); 1196 Value& currentValue(); 1197 Char getNextChar(); 1198 void 1199 getLocationLineAndColumn(Location location, int& line, int& column) const; 1200 std::string getLocationLineAndColumn(Location location) const; 1201 void addComment(Location begin, Location end, CommentPlacement placement); 1202 void skipCommentTokens(Token& token); 1203 1204 typedef std::stack<Value*> Nodes; 1205 Nodes nodes_; 1206 Errors errors_; 1207 std::string document_; 1208 Location begin_; 1209 Location end_; 1210 Location current_; 1211 Location lastValueEnd_; 1212 Value* lastValue_; 1213 std::string commentsBefore_; 1214 int stackDepth_; 1215 1216 OurFeatures const features_; 1217 bool collectComments_; 1218 }; // OurReader 1219 1220 // complete copy of Read impl, for OurReader 1221 1222 OurReader::OurReader(OurFeatures const& features) 1223 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), 1224 lastValue_(), commentsBefore_(), 1225 stackDepth_(0), 1226 features_(features), collectComments_() { 1227 } 1228 1229 bool OurReader::parse(const char* beginDoc, 1230 const char* endDoc, 1231 Value& root, 1232 bool collectComments) { 1233 if (!features_.allowComments_) { 1234 collectComments = false; 1235 } 1236 1237 begin_ = beginDoc; 1238 end_ = endDoc; 1239 collectComments_ = collectComments; 1240 current_ = begin_; 1241 lastValueEnd_ = 0; 1242 lastValue_ = 0; 1243 commentsBefore_ = ""; 1244 errors_.clear(); 1245 while (!nodes_.empty()) 1246 nodes_.pop(); 1247 nodes_.push(&root); 1248 1249 stackDepth_ = 0; 1250 bool successful = readValue(); 1251 Token token; 1252 skipCommentTokens(token); 1253 if (features_.failIfExtra_) { 1254 if (token.type_ != tokenError && token.type_ != tokenEndOfStream) { 1255 addError("Extra non-whitespace after JSON value.", token); 1256 return false; 1257 } 1258 } 1259 if (collectComments_ && !commentsBefore_.empty()) 1260 root.setComment(commentsBefore_, commentAfter); 1261 if (features_.strictRoot_) { 1262 if (!root.isArray() && !root.isObject()) { 1263 // Set error location to start of doc, ideally should be first token found 1264 // in doc 1265 token.type_ = tokenError; 1266 token.start_ = beginDoc; 1267 token.end_ = endDoc; 1268 addError( 1269 "A valid JSON document must be either an array or an object value.", 1270 token); 1271 return false; 1272 } 1273 } 1274 return successful; 1275 } 1276 1277 bool OurReader::readValue() { 1278 if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue()."); 1279 ++stackDepth_; 1280 Token token; 1281 skipCommentTokens(token); 1282 bool successful = true; 1283 1284 if (collectComments_ && !commentsBefore_.empty()) { 1285 currentValue().setComment(commentsBefore_, commentBefore); 1286 commentsBefore_ = ""; 1287 } 1288 1289 switch (token.type_) { 1290 case tokenObjectBegin: 1291 successful = readObject(token); 1292 currentValue().setOffsetLimit(current_ - begin_); 1293 break; 1294 case tokenArrayBegin: 1295 successful = readArray(token); 1296 currentValue().setOffsetLimit(current_ - begin_); 1297 break; 1298 case tokenNumber: 1299 successful = decodeNumber(token); 1300 break; 1301 case tokenString: 1302 successful = decodeString(token); 1303 break; 1304 case tokenTrue: 1305 { 1306 Value v(true); 1307 currentValue().swapPayload(v); 1308 currentValue().setOffsetStart(token.start_ - begin_); 1309 currentValue().setOffsetLimit(token.end_ - begin_); 1310 } 1311 break; 1312 case tokenFalse: 1313 { 1314 Value v(false); 1315 currentValue().swapPayload(v); 1316 currentValue().setOffsetStart(token.start_ - begin_); 1317 currentValue().setOffsetLimit(token.end_ - begin_); 1318 } 1319 break; 1320 case tokenNull: 1321 { 1322 Value v; 1323 currentValue().swapPayload(v); 1324 currentValue().setOffsetStart(token.start_ - begin_); 1325 currentValue().setOffsetLimit(token.end_ - begin_); 1326 } 1327 break; 1328 case tokenNaN: 1329 { 1330 Value v(std::numeric_limits<double>::quiet_NaN()); 1331 currentValue().swapPayload(v); 1332 currentValue().setOffsetStart(token.start_ - begin_); 1333 currentValue().setOffsetLimit(token.end_ - begin_); 1334 } 1335 break; 1336 case tokenPosInf: 1337 { 1338 Value v(std::numeric_limits<double>::infinity()); 1339 currentValue().swapPayload(v); 1340 currentValue().setOffsetStart(token.start_ - begin_); 1341 currentValue().setOffsetLimit(token.end_ - begin_); 1342 } 1343 break; 1344 case tokenNegInf: 1345 { 1346 Value v(-std::numeric_limits<double>::infinity()); 1347 currentValue().swapPayload(v); 1348 currentValue().setOffsetStart(token.start_ - begin_); 1349 currentValue().setOffsetLimit(token.end_ - begin_); 1350 } 1351 break; 1352 case tokenArraySeparator: 1353 case tokenObjectEnd: 1354 case tokenArrayEnd: 1355 if (features_.allowDroppedNullPlaceholders_) { 1356 // "Un-read" the current token and mark the current value as a null 1357 // token. 1358 current_--; 1359 Value v; 1360 currentValue().swapPayload(v); 1361 currentValue().setOffsetStart(current_ - begin_ - 1); 1362 currentValue().setOffsetLimit(current_ - begin_); 1363 break; 1364 } // else, fall through ... 1365 default: 1366 currentValue().setOffsetStart(token.start_ - begin_); 1367 currentValue().setOffsetLimit(token.end_ - begin_); 1368 return addError("Syntax error: value, object or array expected.", token); 1369 } 1370 1371 if (collectComments_) { 1372 lastValueEnd_ = current_; 1373 lastValue_ = ¤tValue(); 1374 } 1375 1376 --stackDepth_; 1377 return successful; 1378 } 1379 1380 void OurReader::skipCommentTokens(Token& token) { 1381 if (features_.allowComments_) { 1382 do { 1383 readToken(token); 1384 } while (token.type_ == tokenComment); 1385 } else { 1386 readToken(token); 1387 } 1388 } 1389 1390 bool OurReader::readToken(Token& token) { 1391 skipSpaces(); 1392 token.start_ = current_; 1393 Char c = getNextChar(); 1394 bool ok = true; 1395 switch (c) { 1396 case '{': 1397 token.type_ = tokenObjectBegin; 1398 break; 1399 case '}': 1400 token.type_ = tokenObjectEnd; 1401 break; 1402 case '[': 1403 token.type_ = tokenArrayBegin; 1404 break; 1405 case ']': 1406 token.type_ = tokenArrayEnd; 1407 break; 1408 case '"': 1409 token.type_ = tokenString; 1410 ok = readString(); 1411 break; 1412 case '\'': 1413 if (features_.allowSingleQuotes_) { 1414 token.type_ = tokenString; 1415 ok = readStringSingleQuote(); 1416 break; 1417 } // else continue 1418 case '/': 1419 token.type_ = tokenComment; 1420 ok = readComment(); 1421 break; 1422 case '0': 1423 case '1': 1424 case '2': 1425 case '3': 1426 case '4': 1427 case '5': 1428 case '6': 1429 case '7': 1430 case '8': 1431 case '9': 1432 token.type_ = tokenNumber; 1433 readNumber(false); 1434 break; 1435 case '-': 1436 if (readNumber(true)) { 1437 token.type_ = tokenNumber; 1438 } else { 1439 token.type_ = tokenNegInf; 1440 ok = features_.allowSpecialFloats_ && match("nfinity", 7); 1441 } 1442 break; 1443 case 't': 1444 token.type_ = tokenTrue; 1445 ok = match("rue", 3); 1446 break; 1447 case 'f': 1448 token.type_ = tokenFalse; 1449 ok = match("alse", 4); 1450 break; 1451 case 'n': 1452 token.type_ = tokenNull; 1453 ok = match("ull", 3); 1454 break; 1455 case 'N': 1456 if (features_.allowSpecialFloats_) { 1457 token.type_ = tokenNaN; 1458 ok = match("aN", 2); 1459 } else { 1460 ok = false; 1461 } 1462 break; 1463 case 'I': 1464 if (features_.allowSpecialFloats_) { 1465 token.type_ = tokenPosInf; 1466 ok = match("nfinity", 7); 1467 } else { 1468 ok = false; 1469 } 1470 break; 1471 case ',': 1472 token.type_ = tokenArraySeparator; 1473 break; 1474 case ':': 1475 token.type_ = tokenMemberSeparator; 1476 break; 1477 case 0: 1478 token.type_ = tokenEndOfStream; 1479 break; 1480 default: 1481 ok = false; 1482 break; 1483 } 1484 if (!ok) 1485 token.type_ = tokenError; 1486 token.end_ = current_; 1487 return true; 1488 } 1489 1490 void OurReader::skipSpaces() { 1491 while (current_ != end_) { 1492 Char c = *current_; 1493 if (c == ' ' || c == '\t' || c == '\r' || c == '\n') 1494 ++current_; 1495 else 1496 break; 1497 } 1498 } 1499 1500 bool OurReader::match(Location pattern, int patternLength) { 1501 if (end_ - current_ < patternLength) 1502 return false; 1503 int index = patternLength; 1504 while (index--) 1505 if (current_[index] != pattern[index]) 1506 return false; 1507 current_ += patternLength; 1508 return true; 1509 } 1510 1511 bool OurReader::readComment() { 1512 Location commentBegin = current_ - 1; 1513 Char c = getNextChar(); 1514 bool successful = false; 1515 if (c == '*') 1516 successful = readCStyleComment(); 1517 else if (c == '/') 1518 successful = readCppStyleComment(); 1519 if (!successful) 1520 return false; 1521 1522 if (collectComments_) { 1523 CommentPlacement placement = commentBefore; 1524 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) { 1525 if (c != '*' || !containsNewLine(commentBegin, current_)) 1526 placement = commentAfterOnSameLine; 1527 } 1528 1529 addComment(commentBegin, current_, placement); 1530 } 1531 return true; 1532 } 1533 1534 void 1535 OurReader::addComment(Location begin, Location end, CommentPlacement placement) { 1536 assert(collectComments_); 1537 const std::string& normalized = normalizeEOL(begin, end); 1538 if (placement == commentAfterOnSameLine) { 1539 assert(lastValue_ != 0); 1540 lastValue_->setComment(normalized, placement); 1541 } else { 1542 commentsBefore_ += normalized; 1543 } 1544 } 1545 1546 bool OurReader::readCStyleComment() { 1547 while (current_ != end_) { 1548 Char c = getNextChar(); 1549 if (c == '*' && *current_ == '/') 1550 break; 1551 } 1552 return getNextChar() == '/'; 1553 } 1554 1555 bool OurReader::readCppStyleComment() { 1556 while (current_ != end_) { 1557 Char c = getNextChar(); 1558 if (c == '\n') 1559 break; 1560 if (c == '\r') { 1561 // Consume DOS EOL. It will be normalized in addComment. 1562 if (current_ != end_ && *current_ == '\n') 1563 getNextChar(); 1564 // Break on Moc OS 9 EOL. 1565 break; 1566 } 1567 } 1568 return true; 1569 } 1570 1571 bool OurReader::readNumber(bool checkInf) { 1572 const char *p = current_; 1573 if (checkInf && p != end_ && *p == 'I') { 1574 current_ = ++p; 1575 return false; 1576 } 1577 char c = '0'; // stopgap for already consumed character 1578 // integral part 1579 while (c >= '0' && c <= '9') 1580 c = (current_ = p) < end_ ? *p++ : 0; 1581 // fractional part 1582 if (c == '.') { 1583 c = (current_ = p) < end_ ? *p++ : 0; 1584 while (c >= '0' && c <= '9') 1585 c = (current_ = p) < end_ ? *p++ : 0; 1586 } 1587 // exponential part 1588 if (c == 'e' || c == 'E') { 1589 c = (current_ = p) < end_ ? *p++ : 0; 1590 if (c == '+' || c == '-') 1591 c = (current_ = p) < end_ ? *p++ : 0; 1592 while (c >= '0' && c <= '9') 1593 c = (current_ = p) < end_ ? *p++ : 0; 1594 } 1595 return true; 1596 } 1597 bool OurReader::readString() { 1598 Char c = 0; 1599 while (current_ != end_) { 1600 c = getNextChar(); 1601 if (c == '\\') 1602 getNextChar(); 1603 else if (c == '"') 1604 break; 1605 } 1606 return c == '"'; 1607 } 1608 1609 1610 bool OurReader::readStringSingleQuote() { 1611 Char c = 0; 1612 while (current_ != end_) { 1613 c = getNextChar(); 1614 if (c == '\\') 1615 getNextChar(); 1616 else if (c == '\'') 1617 break; 1618 } 1619 return c == '\''; 1620 } 1621 1622 bool OurReader::readObject(Token& tokenStart) { 1623 Token tokenName; 1624 std::string name; 1625 Value init(objectValue); 1626 currentValue().swapPayload(init); 1627 currentValue().setOffsetStart(tokenStart.start_ - begin_); 1628 while (readToken(tokenName)) { 1629 bool initialTokenOk = true; 1630 while (tokenName.type_ == tokenComment && initialTokenOk) 1631 initialTokenOk = readToken(tokenName); 1632 if (!initialTokenOk) 1633 break; 1634 if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object 1635 return true; 1636 name = ""; 1637 if (tokenName.type_ == tokenString) { 1638 if (!decodeString(tokenName, name)) 1639 return recoverFromError(tokenObjectEnd); 1640 } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) { 1641 Value numberName; 1642 if (!decodeNumber(tokenName, numberName)) 1643 return recoverFromError(tokenObjectEnd); 1644 name = numberName.asString(); 1645 } else { 1646 break; 1647 } 1648 1649 Token colon; 1650 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) { 1651 return addErrorAndRecover( 1652 "Missing ':' after object member name", colon, tokenObjectEnd); 1653 } 1654 if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30"); 1655 if (features_.rejectDupKeys_ && currentValue().isMember(name)) { 1656 std::string msg = "Duplicate key: '" + name + "'"; 1657 return addErrorAndRecover( 1658 msg, tokenName, tokenObjectEnd); 1659 } 1660 Value& value = currentValue()[name]; 1661 nodes_.push(&value); 1662 bool ok = readValue(); 1663 nodes_.pop(); 1664 if (!ok) // error already set 1665 return recoverFromError(tokenObjectEnd); 1666 1667 Token comma; 1668 if (!readToken(comma) || 1669 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator && 1670 comma.type_ != tokenComment)) { 1671 return addErrorAndRecover( 1672 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd); 1673 } 1674 bool finalizeTokenOk = true; 1675 while (comma.type_ == tokenComment && finalizeTokenOk) 1676 finalizeTokenOk = readToken(comma); 1677 if (comma.type_ == tokenObjectEnd) 1678 return true; 1679 } 1680 return addErrorAndRecover( 1681 "Missing '}' or object member name", tokenName, tokenObjectEnd); 1682 } 1683 1684 bool OurReader::readArray(Token& tokenStart) { 1685 Value init(arrayValue); 1686 currentValue().swapPayload(init); 1687 currentValue().setOffsetStart(tokenStart.start_ - begin_); 1688 skipSpaces(); 1689 if (*current_ == ']') // empty array 1690 { 1691 Token endArray; 1692 readToken(endArray); 1693 return true; 1694 } 1695 int index = 0; 1696 for (;;) { 1697 Value& value = currentValue()[index++]; 1698 nodes_.push(&value); 1699 bool ok = readValue(); 1700 nodes_.pop(); 1701 if (!ok) // error already set 1702 return recoverFromError(tokenArrayEnd); 1703 1704 Token token; 1705 // Accept Comment after last item in the array. 1706 ok = readToken(token); 1707 while (token.type_ == tokenComment && ok) { 1708 ok = readToken(token); 1709 } 1710 bool badTokenType = 1711 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd); 1712 if (!ok || badTokenType) { 1713 return addErrorAndRecover( 1714 "Missing ',' or ']' in array declaration", token, tokenArrayEnd); 1715 } 1716 if (token.type_ == tokenArrayEnd) 1717 break; 1718 } 1719 return true; 1720 } 1721 1722 bool OurReader::decodeNumber(Token& token) { 1723 Value decoded; 1724 if (!decodeNumber(token, decoded)) 1725 return false; 1726 currentValue().swapPayload(decoded); 1727 currentValue().setOffsetStart(token.start_ - begin_); 1728 currentValue().setOffsetLimit(token.end_ - begin_); 1729 return true; 1730 } 1731 1732 bool OurReader::decodeNumber(Token& token, Value& decoded) { 1733 // Attempts to parse the number as an integer. If the number is 1734 // larger than the maximum supported value of an integer then 1735 // we decode the number as a double. 1736 Location current = token.start_; 1737 bool isNegative = *current == '-'; 1738 if (isNegative) 1739 ++current; 1740 // TODO: Help the compiler do the div and mod at compile time or get rid of them. 1741 Value::LargestUInt maxIntegerValue = 1742 isNegative ? Value::LargestUInt(-Value::minLargestInt) 1743 : Value::maxLargestUInt; 1744 Value::LargestUInt threshold = maxIntegerValue / 10; 1745 Value::LargestUInt value = 0; 1746 while (current < token.end_) { 1747 Char c = *current++; 1748 if (c < '0' || c > '9') 1749 return decodeDouble(token, decoded); 1750 Value::UInt digit(c - '0'); 1751 if (value >= threshold) { 1752 // We've hit or exceeded the max value divided by 10 (rounded down). If 1753 // a) we've only just touched the limit, b) this is the last digit, and 1754 // c) it's small enough to fit in that rounding delta, we're okay. 1755 // Otherwise treat this number as a double to avoid overflow. 1756 if (value > threshold || current != token.end_ || 1757 digit > maxIntegerValue % 10) { 1758 return decodeDouble(token, decoded); 1759 } 1760 } 1761 value = value * 10 + digit; 1762 } 1763 if (isNegative) 1764 decoded = -Value::LargestInt(value); 1765 else if (value <= Value::LargestUInt(Value::maxInt)) 1766 decoded = Value::LargestInt(value); 1767 else 1768 decoded = value; 1769 return true; 1770 } 1771 1772 bool OurReader::decodeDouble(Token& token) { 1773 Value decoded; 1774 if (!decodeDouble(token, decoded)) 1775 return false; 1776 currentValue().swapPayload(decoded); 1777 currentValue().setOffsetStart(token.start_ - begin_); 1778 currentValue().setOffsetLimit(token.end_ - begin_); 1779 return true; 1780 } 1781 1782 bool OurReader::decodeDouble(Token& token, Value& decoded) { 1783 double value = 0; 1784 const int bufferSize = 32; 1785 int count; 1786 int length = int(token.end_ - token.start_); 1787 1788 // Sanity check to avoid buffer overflow exploits. 1789 if (length < 0) { 1790 return addError("Unable to parse token length", token); 1791 } 1792 1793 // Avoid using a string constant for the format control string given to 1794 // sscanf, as this can cause hard to debug crashes on OS X. See here for more 1795 // info: 1796 // 1797 // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html 1798 char format[] = "%lf"; 1799 1800 if (length <= bufferSize) { 1801 Char buffer[bufferSize + 1]; 1802 memcpy(buffer, token.start_, length); 1803 buffer[length] = 0; 1804 count = sscanf(buffer, format, &value); 1805 } else { 1806 std::string buffer(token.start_, token.end_); 1807 count = sscanf(buffer.c_str(), format, &value); 1808 } 1809 1810 if (count != 1) 1811 return addError("'" + std::string(token.start_, token.end_) + 1812 "' is not a number.", 1813 token); 1814 decoded = value; 1815 return true; 1816 } 1817 1818 bool OurReader::decodeString(Token& token) { 1819 std::string decoded_string; 1820 if (!decodeString(token, decoded_string)) 1821 return false; 1822 Value decoded(decoded_string); 1823 currentValue().swapPayload(decoded); 1824 currentValue().setOffsetStart(token.start_ - begin_); 1825 currentValue().setOffsetLimit(token.end_ - begin_); 1826 return true; 1827 } 1828 1829 bool OurReader::decodeString(Token& token, std::string& decoded) { 1830 decoded.reserve(token.end_ - token.start_ - 2); 1831 Location current = token.start_ + 1; // skip '"' 1832 Location end = token.end_ - 1; // do not include '"' 1833 while (current != end) { 1834 Char c = *current++; 1835 if (c == '"') 1836 break; 1837 else if (c == '\\') { 1838 if (current == end) 1839 return addError("Empty escape sequence in string", token, current); 1840 Char escape = *current++; 1841 switch (escape) { 1842 case '"': 1843 decoded += '"'; 1844 break; 1845 case '/': 1846 decoded += '/'; 1847 break; 1848 case '\\': 1849 decoded += '\\'; 1850 break; 1851 case 'b': 1852 decoded += '\b'; 1853 break; 1854 case 'f': 1855 decoded += '\f'; 1856 break; 1857 case 'n': 1858 decoded += '\n'; 1859 break; 1860 case 'r': 1861 decoded += '\r'; 1862 break; 1863 case 't': 1864 decoded += '\t'; 1865 break; 1866 case 'u': { 1867 unsigned int unicode; 1868 if (!decodeUnicodeCodePoint(token, current, end, unicode)) 1869 return false; 1870 decoded += codePointToUTF8(unicode); 1871 } break; 1872 default: 1873 return addError("Bad escape sequence in string", token, current); 1874 } 1875 } else { 1876 decoded += c; 1877 } 1878 } 1879 return true; 1880 } 1881 1882 bool OurReader::decodeUnicodeCodePoint(Token& token, 1883 Location& current, 1884 Location end, 1885 unsigned int& unicode) { 1886 1887 if (!decodeUnicodeEscapeSequence(token, current, end, unicode)) 1888 return false; 1889 if (unicode >= 0xD800 && unicode <= 0xDBFF) { 1890 // surrogate pairs 1891 if (end - current < 6) 1892 return addError( 1893 "additional six characters expected to parse unicode surrogate pair.", 1894 token, 1895 current); 1896 unsigned int surrogatePair; 1897 if (*(current++) == '\\' && *(current++) == 'u') { 1898 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) { 1899 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF); 1900 } else 1901 return false; 1902 } else 1903 return addError("expecting another \\u token to begin the second half of " 1904 "a unicode surrogate pair", 1905 token, 1906 current); 1907 } 1908 return true; 1909 } 1910 1911 bool OurReader::decodeUnicodeEscapeSequence(Token& token, 1912 Location& current, 1913 Location end, 1914 unsigned int& unicode) { 1915 if (end - current < 4) 1916 return addError( 1917 "Bad unicode escape sequence in string: four digits expected.", 1918 token, 1919 current); 1920 unicode = 0; 1921 for (int index = 0; index < 4; ++index) { 1922 Char c = *current++; 1923 unicode *= 16; 1924 if (c >= '0' && c <= '9') 1925 unicode += c - '0'; 1926 else if (c >= 'a' && c <= 'f') 1927 unicode += c - 'a' + 10; 1928 else if (c >= 'A' && c <= 'F') 1929 unicode += c - 'A' + 10; 1930 else 1931 return addError( 1932 "Bad unicode escape sequence in string: hexadecimal digit expected.", 1933 token, 1934 current); 1935 } 1936 return true; 1937 } 1938 1939 bool 1940 OurReader::addError(const std::string& message, Token& token, Location extra) { 1941 ErrorInfo info; 1942 info.token_ = token; 1943 info.message_ = message; 1944 info.extra_ = extra; 1945 errors_.push_back(info); 1946 return false; 1947 } 1948 1949 bool OurReader::recoverFromError(TokenType skipUntilToken) { 1950 int errorCount = int(errors_.size()); 1951 Token skip; 1952 for (;;) { 1953 if (!readToken(skip)) 1954 errors_.resize(errorCount); // discard errors caused by recovery 1955 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream) 1956 break; 1957 } 1958 errors_.resize(errorCount); 1959 return false; 1960 } 1961 1962 bool OurReader::addErrorAndRecover(const std::string& message, 1963 Token& token, 1964 TokenType skipUntilToken) { 1965 addError(message, token); 1966 return recoverFromError(skipUntilToken); 1967 } 1968 1969 Value& OurReader::currentValue() { return *(nodes_.top()); } 1970 1971 OurReader::Char OurReader::getNextChar() { 1972 if (current_ == end_) 1973 return 0; 1974 return *current_++; 1975 } 1976 1977 void OurReader::getLocationLineAndColumn(Location location, 1978 int& line, 1979 int& column) const { 1980 Location current = begin_; 1981 Location lastLineStart = current; 1982 line = 0; 1983 while (current < location && current != end_) { 1984 Char c = *current++; 1985 if (c == '\r') { 1986 if (*current == '\n') 1987 ++current; 1988 lastLineStart = current; 1989 ++line; 1990 } else if (c == '\n') { 1991 lastLineStart = current; 1992 ++line; 1993 } 1994 } 1995 // column & line start at 1 1996 column = int(location - lastLineStart) + 1; 1997 ++line; 1998 } 1999 2000 std::string OurReader::getLocationLineAndColumn(Location location) const { 2001 int line, column; 2002 getLocationLineAndColumn(location, line, column); 2003 char buffer[18 + 16 + 16 + 1]; 2004 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column); 2005 return buffer; 2006 } 2007 2008 std::string OurReader::getFormattedErrorMessages() const { 2009 std::string formattedMessage; 2010 for (Errors::const_iterator itError = errors_.begin(); 2011 itError != errors_.end(); 2012 ++itError) { 2013 const ErrorInfo& error = *itError; 2014 formattedMessage += 2015 "* " + getLocationLineAndColumn(error.token_.start_) + "\n"; 2016 formattedMessage += " " + error.message_ + "\n"; 2017 if (error.extra_) 2018 formattedMessage += 2019 "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n"; 2020 } 2021 return formattedMessage; 2022 } 2023 2024 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const { 2025 std::vector<OurReader::StructuredError> allErrors; 2026 for (Errors::const_iterator itError = errors_.begin(); 2027 itError != errors_.end(); 2028 ++itError) { 2029 const ErrorInfo& error = *itError; 2030 OurReader::StructuredError structured; 2031 structured.offset_start = error.token_.start_ - begin_; 2032 structured.offset_limit = error.token_.end_ - begin_; 2033 structured.message = error.message_; 2034 allErrors.push_back(structured); 2035 } 2036 return allErrors; 2037 } 2038 2039 bool OurReader::pushError(const Value& value, const std::string& message) { 2040 size_t length = end_ - begin_; 2041 if(value.getOffsetStart() > length 2042 || value.getOffsetLimit() > length) 2043 return false; 2044 Token token; 2045 token.type_ = tokenError; 2046 token.start_ = begin_ + value.getOffsetStart(); 2047 token.end_ = end_ + value.getOffsetLimit(); 2048 ErrorInfo info; 2049 info.token_ = token; 2050 info.message_ = message; 2051 info.extra_ = 0; 2052 errors_.push_back(info); 2053 return true; 2054 } 2055 2056 bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) { 2057 size_t length = end_ - begin_; 2058 if(value.getOffsetStart() > length 2059 || value.getOffsetLimit() > length 2060 || extra.getOffsetLimit() > length) 2061 return false; 2062 Token token; 2063 token.type_ = tokenError; 2064 token.start_ = begin_ + value.getOffsetStart(); 2065 token.end_ = begin_ + value.getOffsetLimit(); 2066 ErrorInfo info; 2067 info.token_ = token; 2068 info.message_ = message; 2069 info.extra_ = begin_ + extra.getOffsetStart(); 2070 errors_.push_back(info); 2071 return true; 2072 } 2073 2074 bool OurReader::good() const { 2075 return !errors_.size(); 2076 } 2077 2078 2079 class OurCharReader : public CharReader { 2080 bool const collectComments_; 2081 OurReader reader_; 2082 public: 2083 OurCharReader( 2084 bool collectComments, 2085 OurFeatures const& features) 2086 : collectComments_(collectComments) 2087 , reader_(features) 2088 {} 2089 bool parse( 2090 char const* beginDoc, char const* endDoc, 2091 Value* root, std::string* errs) override { 2092 bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_); 2093 if (errs) { 2094 *errs = reader_.getFormattedErrorMessages(); 2095 } 2096 return ok; 2097 } 2098 }; 2099 2100 CharReaderBuilder::CharReaderBuilder() 2101 { 2102 setDefaults(&settings_); 2103 } 2104 CharReaderBuilder::~CharReaderBuilder() 2105 {} 2106 CharReader* CharReaderBuilder::newCharReader() const 2107 { 2108 bool collectComments = settings_["collectComments"].asBool(); 2109 OurFeatures features = OurFeatures::all(); 2110 features.allowComments_ = settings_["allowComments"].asBool(); 2111 features.strictRoot_ = settings_["strictRoot"].asBool(); 2112 features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool(); 2113 features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool(); 2114 features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool(); 2115 features.stackLimit_ = settings_["stackLimit"].asInt(); 2116 features.failIfExtra_ = settings_["failIfExtra"].asBool(); 2117 features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); 2118 features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); 2119 return new OurCharReader(collectComments, features); 2120 } 2121 static void getValidReaderKeys(std::set<std::string>* valid_keys) 2122 { 2123 valid_keys->clear(); 2124 valid_keys->insert("collectComments"); 2125 valid_keys->insert("allowComments"); 2126 valid_keys->insert("strictRoot"); 2127 valid_keys->insert("allowDroppedNullPlaceholders"); 2128 valid_keys->insert("allowNumericKeys"); 2129 valid_keys->insert("allowSingleQuotes"); 2130 valid_keys->insert("stackLimit"); 2131 valid_keys->insert("failIfExtra"); 2132 valid_keys->insert("rejectDupKeys"); 2133 valid_keys->insert("allowSpecialFloats"); 2134 } 2135 bool CharReaderBuilder::validate(Json::Value* invalid) const 2136 { 2137 Json::Value my_invalid; 2138 if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL 2139 Json::Value& inv = *invalid; 2140 std::set<std::string> valid_keys; 2141 getValidReaderKeys(&valid_keys); 2142 Value::Members keys = settings_.getMemberNames(); 2143 size_t n = keys.size(); 2144 for (size_t i = 0; i < n; ++i) { 2145 std::string const& key = keys[i]; 2146 if (valid_keys.find(key) == valid_keys.end()) { 2147 inv[key] = settings_[key]; 2148 } 2149 } 2150 return 0u == inv.size(); 2151 } 2152 Value& CharReaderBuilder::operator[](std::string key) 2153 { 2154 return settings_[key]; 2155 } 2156 // static 2157 void CharReaderBuilder::strictMode(Json::Value* settings) 2158 { 2159 //! [CharReaderBuilderStrictMode] 2160 (*settings)["allowComments"] = false; 2161 (*settings)["strictRoot"] = true; 2162 (*settings)["allowDroppedNullPlaceholders"] = false; 2163 (*settings)["allowNumericKeys"] = false; 2164 (*settings)["allowSingleQuotes"] = false; 2165 (*settings)["stackLimit"] = 1000; 2166 (*settings)["failIfExtra"] = true; 2167 (*settings)["rejectDupKeys"] = true; 2168 (*settings)["allowSpecialFloats"] = false; 2169 //! [CharReaderBuilderStrictMode] 2170 } 2171 // static 2172 void CharReaderBuilder::setDefaults(Json::Value* settings) 2173 { 2174 //! [CharReaderBuilderDefaults] 2175 (*settings)["collectComments"] = true; 2176 (*settings)["allowComments"] = true; 2177 (*settings)["strictRoot"] = false; 2178 (*settings)["allowDroppedNullPlaceholders"] = false; 2179 (*settings)["allowNumericKeys"] = false; 2180 (*settings)["allowSingleQuotes"] = false; 2181 (*settings)["stackLimit"] = 1000; 2182 (*settings)["failIfExtra"] = false; 2183 (*settings)["rejectDupKeys"] = false; 2184 (*settings)["allowSpecialFloats"] = false; 2185 //! [CharReaderBuilderDefaults] 2186 } 2187 2188 ////////////////////////////////// 2189 // global functions 2190 2191 bool parseFromStream( 2192 CharReader::Factory const& fact, std::istream& sin, 2193 Value* root, std::string* errs) 2194 { 2195 std::ostringstream ssin; 2196 ssin << sin.rdbuf(); 2197 std::string doc = ssin.str(); 2198 char const* begin = doc.data(); 2199 char const* end = begin + doc.size(); 2200 // Note that we do not actually need a null-terminator. 2201 CharReaderPtr const reader(fact.newCharReader()); 2202 return reader->parse(begin, end, root, errs); 2203 } 2204 2205 std::istream& operator>>(std::istream& sin, Value& root) { 2206 CharReaderBuilder b; 2207 std::string errs; 2208 bool ok = parseFromStream(b, sin, &root, &errs); 2209 if (!ok) { 2210 fprintf(stderr, 2211 "Error from reader: %s", 2212 errs.c_str()); 2213 2214 throwRuntimeError(errs); 2215 } 2216 return sin; 2217 } 2218 2219 } // namespace Json 2220 2221 // ////////////////////////////////////////////////////////////////////// 2222 // End of content of file: src/lib_json/json_reader.cpp 2223 // ////////////////////////////////////////////////////////////////////// 2224 2225 2226 2227 2228 2229 2230 // ////////////////////////////////////////////////////////////////////// 2231 // Beginning of content of file: src/lib_json/json_valueiterator.inl 2232 // ////////////////////////////////////////////////////////////////////// 2233 2234 // Copyright 2007-2010 Baptiste Lepilleur 2235 // Distributed under MIT license, or public domain if desired and 2236 // recognized in your jurisdiction. 2237 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2238 2239 // included by json_value.cpp 2240 2241 namespace Json { 2242 2243 // ////////////////////////////////////////////////////////////////// 2244 // ////////////////////////////////////////////////////////////////// 2245 // ////////////////////////////////////////////////////////////////// 2246 // class ValueIteratorBase 2247 // ////////////////////////////////////////////////////////////////// 2248 // ////////////////////////////////////////////////////////////////// 2249 // ////////////////////////////////////////////////////////////////// 2250 2251 ValueIteratorBase::ValueIteratorBase() 2252 : current_(), isNull_(true) { 2253 } 2254 2255 ValueIteratorBase::ValueIteratorBase( 2256 const Value::ObjectValues::iterator& current) 2257 : current_(current), isNull_(false) {} 2258 2259 Value& ValueIteratorBase::deref() const { 2260 return current_->second; 2261 } 2262 2263 void ValueIteratorBase::increment() { 2264 ++current_; 2265 } 2266 2267 void ValueIteratorBase::decrement() { 2268 --current_; 2269 } 2270 2271 ValueIteratorBase::difference_type 2272 ValueIteratorBase::computeDistance(const SelfType& other) const { 2273 #ifdef JSON_USE_CPPTL_SMALLMAP 2274 return other.current_ - current_; 2275 #else 2276 // Iterator for null value are initialized using the default 2277 // constructor, which initialize current_ to the default 2278 // std::map::iterator. As begin() and end() are two instance 2279 // of the default std::map::iterator, they can not be compared. 2280 // To allow this, we handle this comparison specifically. 2281 if (isNull_ && other.isNull_) { 2282 return 0; 2283 } 2284 2285 // Usage of std::distance is not portable (does not compile with Sun Studio 12 2286 // RogueWave STL, 2287 // which is the one used by default). 2288 // Using a portable hand-made version for non random iterator instead: 2289 // return difference_type( std::distance( current_, other.current_ ) ); 2290 difference_type myDistance = 0; 2291 for (Value::ObjectValues::iterator it = current_; it != other.current_; 2292 ++it) { 2293 ++myDistance; 2294 } 2295 return myDistance; 2296 #endif 2297 } 2298 2299 bool ValueIteratorBase::isEqual(const SelfType& other) const { 2300 if (isNull_) { 2301 return other.isNull_; 2302 } 2303 return current_ == other.current_; 2304 } 2305 2306 void ValueIteratorBase::copy(const SelfType& other) { 2307 current_ = other.current_; 2308 isNull_ = other.isNull_; 2309 } 2310 2311 Value ValueIteratorBase::key() const { 2312 const Value::CZString czstring = (*current_).first; 2313 if (czstring.data()) { 2314 if (czstring.isStaticString()) 2315 return Value(StaticString(czstring.data())); 2316 return Value(czstring.data(), czstring.data() + czstring.length()); 2317 } 2318 return Value(czstring.index()); 2319 } 2320 2321 UInt ValueIteratorBase::index() const { 2322 const Value::CZString czstring = (*current_).first; 2323 if (!czstring.data()) 2324 return czstring.index(); 2325 return Value::UInt(-1); 2326 } 2327 2328 std::string ValueIteratorBase::name() const { 2329 char const* keey; 2330 char const* end; 2331 keey = memberName(&end); 2332 if (!keey) return std::string(); 2333 return std::string(keey, end); 2334 } 2335 2336 char const* ValueIteratorBase::memberName() const { 2337 const char* cname = (*current_).first.data(); 2338 return cname ? cname : ""; 2339 } 2340 2341 char const* ValueIteratorBase::memberName(char const** end) const { 2342 const char* cname = (*current_).first.data(); 2343 if (!cname) { 2344 *end = NULL; 2345 return NULL; 2346 } 2347 *end = cname + (*current_).first.length(); 2348 return cname; 2349 } 2350 2351 // ////////////////////////////////////////////////////////////////// 2352 // ////////////////////////////////////////////////////////////////// 2353 // ////////////////////////////////////////////////////////////////// 2354 // class ValueConstIterator 2355 // ////////////////////////////////////////////////////////////////// 2356 // ////////////////////////////////////////////////////////////////// 2357 // ////////////////////////////////////////////////////////////////// 2358 2359 ValueConstIterator::ValueConstIterator() {} 2360 2361 ValueConstIterator::ValueConstIterator( 2362 const Value::ObjectValues::iterator& current) 2363 : ValueIteratorBase(current) {} 2364 2365 ValueConstIterator::ValueConstIterator(ValueIterator const& other) 2366 : ValueIteratorBase(other) {} 2367 2368 ValueConstIterator& ValueConstIterator:: 2369 operator=(const ValueIteratorBase& other) { 2370 copy(other); 2371 return *this; 2372 } 2373 2374 // ////////////////////////////////////////////////////////////////// 2375 // ////////////////////////////////////////////////////////////////// 2376 // ////////////////////////////////////////////////////////////////// 2377 // class ValueIterator 2378 // ////////////////////////////////////////////////////////////////// 2379 // ////////////////////////////////////////////////////////////////// 2380 // ////////////////////////////////////////////////////////////////// 2381 2382 ValueIterator::ValueIterator() {} 2383 2384 ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current) 2385 : ValueIteratorBase(current) {} 2386 2387 ValueIterator::ValueIterator(const ValueConstIterator& other) 2388 : ValueIteratorBase(other) { 2389 throwRuntimeError("ConstIterator to Iterator should never be allowed."); 2390 } 2391 2392 ValueIterator::ValueIterator(const ValueIterator& other) 2393 : ValueIteratorBase(other) {} 2394 2395 ValueIterator& ValueIterator::operator=(const SelfType& other) { 2396 copy(other); 2397 return *this; 2398 } 2399 2400 } // namespace Json 2401 2402 // ////////////////////////////////////////////////////////////////////// 2403 // End of content of file: src/lib_json/json_valueiterator.inl 2404 // ////////////////////////////////////////////////////////////////////// 2405 2406 2407 2408 2409 2410 2411 // ////////////////////////////////////////////////////////////////////// 2412 // Beginning of content of file: src/lib_json/json_value.cpp 2413 // ////////////////////////////////////////////////////////////////////// 2414 2415 // Copyright 2011 Baptiste Lepilleur 2416 // Distributed under MIT license, or public domain if desired and 2417 // recognized in your jurisdiction. 2418 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 2419 2420 #if !defined(JSON_IS_AMALGAMATION) 2421 #include <json/assertions.h> 2422 #include <json/value.h> 2423 #include <json/writer.h> 2424 #endif // if !defined(JSON_IS_AMALGAMATION) 2425 #include <math.h> 2426 #include <sstream> 2427 #include <utility> 2428 #include <cstring> 2429 #include <cassert> 2430 #ifdef JSON_USE_CPPTL 2431 #include <cpptl/conststring.h> 2432 #endif 2433 #include <cstddef> // size_t 2434 #include <algorithm> // min() 2435 2436 #define JSON_ASSERT_UNREACHABLE assert(false) 2437 2438 namespace Json { 2439 2440 // This is a walkaround to avoid the static initialization of Value::null. 2441 // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of 2442 // 8 (instead of 4) as a bit of future-proofing. 2443 #if defined(__ARMEL__) 2444 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment))) 2445 #else 2446 #define ALIGNAS(byte_alignment) 2447 #endif 2448 static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 }; 2449 const unsigned char& kNullRef = kNull[0]; 2450 const Value& Value::null = reinterpret_cast<const Value&>(kNullRef); 2451 const Value& Value::nullRef = null; 2452 2453 const Int Value::minInt = Int(~(UInt(-1) / 2)); 2454 const Int Value::maxInt = Int(UInt(-1) / 2); 2455 const UInt Value::maxUInt = UInt(-1); 2456 #if defined(JSON_HAS_INT64) 2457 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2)); 2458 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2); 2459 const UInt64 Value::maxUInt64 = UInt64(-1); 2460 // The constant is hard-coded because some compiler have trouble 2461 // converting Value::maxUInt64 to a double correctly (AIX/xlC). 2462 // Assumes that UInt64 is a 64 bits integer. 2463 static const double maxUInt64AsDouble = 18446744073709551615.0; 2464 #endif // defined(JSON_HAS_INT64) 2465 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2)); 2466 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2); 2467 const LargestUInt Value::maxLargestUInt = LargestUInt(-1); 2468 2469 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2470 template <typename T, typename U> 2471 static inline bool InRange(double d, T min, U max) { 2472 return d >= min && d <= max; 2473 } 2474 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2475 static inline double integerToDouble(Json::UInt64 value) { 2476 return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1); 2477 } 2478 2479 template <typename T> static inline double integerToDouble(T value) { 2480 return static_cast<double>(value); 2481 } 2482 2483 template <typename T, typename U> 2484 static inline bool InRange(double d, T min, U max) { 2485 return d >= integerToDouble(min) && d <= integerToDouble(max); 2486 } 2487 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 2488 2489 /** Duplicates the specified string value. 2490 * @param value Pointer to the string to duplicate. Must be zero-terminated if 2491 * length is "unknown". 2492 * @param length Length of the value. if equals to unknown, then it will be 2493 * computed using strlen(value). 2494 * @return Pointer on the duplicate instance of string. 2495 */ 2496 static inline char* duplicateStringValue(const char* value, 2497 size_t length) { 2498 // Avoid an integer overflow in the call to malloc below by limiting length 2499 // to a sane value. 2500 if (length >= (size_t)Value::maxInt) 2501 length = Value::maxInt - 1; 2502 2503 char* newString = static_cast<char*>(malloc(length + 1)); 2504 if (newString == NULL) { 2505 throwRuntimeError( 2506 "in Json::Value::duplicateStringValue(): " 2507 "Failed to allocate string value buffer"); 2508 } 2509 memcpy(newString, value, length); 2510 newString[length] = 0; 2511 return newString; 2512 } 2513 2514 /* Record the length as a prefix. 2515 */ 2516 static inline char* duplicateAndPrefixStringValue( 2517 const char* value, 2518 unsigned int length) 2519 { 2520 // Avoid an integer overflow in the call to malloc below by limiting length 2521 // to a sane value. 2522 JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U, 2523 "in Json::Value::duplicateAndPrefixStringValue(): " 2524 "length too big for prefixing"); 2525 unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; 2526 char* newString = static_cast<char*>(malloc(actualLength)); 2527 if (newString == 0) { 2528 throwRuntimeError( 2529 "in Json::Value::duplicateAndPrefixStringValue(): " 2530 "Failed to allocate string value buffer"); 2531 } 2532 *reinterpret_cast<unsigned*>(newString) = length; 2533 memcpy(newString + sizeof(unsigned), value, length); 2534 newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later 2535 return newString; 2536 } 2537 inline static void decodePrefixedString( 2538 bool isPrefixed, char const* prefixed, 2539 unsigned* length, char const** value) 2540 { 2541 if (!isPrefixed) { 2542 *length = static_cast<unsigned>(strlen(prefixed)); 2543 *value = prefixed; 2544 } else { 2545 *length = *reinterpret_cast<unsigned const*>(prefixed); 2546 *value = prefixed + sizeof(unsigned); 2547 } 2548 } 2549 /** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue(). 2550 */ 2551 static inline void releaseStringValue(char* value) { free(value); } 2552 2553 } // namespace Json 2554 2555 // ////////////////////////////////////////////////////////////////// 2556 // ////////////////////////////////////////////////////////////////// 2557 // ////////////////////////////////////////////////////////////////// 2558 // ValueInternals... 2559 // ////////////////////////////////////////////////////////////////// 2560 // ////////////////////////////////////////////////////////////////// 2561 // ////////////////////////////////////////////////////////////////// 2562 #if !defined(JSON_IS_AMALGAMATION) 2563 2564 #include "json_valueiterator.inl" 2565 #endif // if !defined(JSON_IS_AMALGAMATION) 2566 2567 namespace Json { 2568 2569 Exception::Exception(std::string const& msg) 2570 : msg_(msg) 2571 {} 2572 Exception::~Exception() throw() 2573 {} 2574 char const* Exception::what() const throw() 2575 { 2576 return msg_.c_str(); 2577 } 2578 RuntimeError::RuntimeError(std::string const& msg) 2579 : Exception(msg) 2580 {} 2581 LogicError::LogicError(std::string const& msg) 2582 : Exception(msg) 2583 {} 2584 void throwRuntimeError(std::string const& msg) 2585 { 2586 throw RuntimeError(msg); 2587 } 2588 void throwLogicError(std::string const& msg) 2589 { 2590 throw LogicError(msg); 2591 } 2592 2593 // ////////////////////////////////////////////////////////////////// 2594 // ////////////////////////////////////////////////////////////////// 2595 // ////////////////////////////////////////////////////////////////// 2596 // class Value::CommentInfo 2597 // ////////////////////////////////////////////////////////////////// 2598 // ////////////////////////////////////////////////////////////////// 2599 // ////////////////////////////////////////////////////////////////// 2600 2601 Value::CommentInfo::CommentInfo() : comment_(0) {} 2602 2603 Value::CommentInfo::~CommentInfo() { 2604 if (comment_) 2605 releaseStringValue(comment_); 2606 } 2607 2608 void Value::CommentInfo::setComment(const char* text, size_t len) { 2609 if (comment_) { 2610 releaseStringValue(comment_); 2611 comment_ = 0; 2612 } 2613 JSON_ASSERT(text != 0); 2614 JSON_ASSERT_MESSAGE( 2615 text[0] == '\0' || text[0] == '/', 2616 "in Json::Value::setComment(): Comments must start with /"); 2617 // It seems that /**/ style comments are acceptable as well. 2618 comment_ = duplicateStringValue(text, len); 2619 } 2620 2621 // ////////////////////////////////////////////////////////////////// 2622 // ////////////////////////////////////////////////////////////////// 2623 // ////////////////////////////////////////////////////////////////// 2624 // class Value::CZString 2625 // ////////////////////////////////////////////////////////////////// 2626 // ////////////////////////////////////////////////////////////////// 2627 // ////////////////////////////////////////////////////////////////// 2628 2629 // Notes: policy_ indicates if the string was allocated when 2630 // a string is stored. 2631 2632 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {} 2633 2634 Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate) 2635 : cstr_(str) { 2636 // allocate != duplicate 2637 storage_.policy_ = allocate & 0x3; 2638 storage_.length_ = ulength & 0x3FFFFFFF; 2639 } 2640 2641 Value::CZString::CZString(const CZString& other) 2642 : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0 2643 ? duplicateStringValue(other.cstr_, other.storage_.length_) 2644 : other.cstr_) { 2645 storage_.policy_ = (other.cstr_ 2646 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication 2647 ? noDuplication : duplicate) 2648 : static_cast<DuplicationPolicy>(other.storage_.policy_)); 2649 storage_.length_ = other.storage_.length_; 2650 } 2651 2652 #if JSON_HAS_RVALUE_REFERENCES 2653 Value::CZString::CZString(CZString&& other) 2654 : cstr_(other.cstr_), index_(other.index_) { 2655 other.cstr_ = nullptr; 2656 } 2657 #endif 2658 2659 Value::CZString::~CZString() { 2660 if (cstr_ && storage_.policy_ == duplicate) 2661 releaseStringValue(const_cast<char*>(cstr_)); 2662 } 2663 2664 void Value::CZString::swap(CZString& other) { 2665 std::swap(cstr_, other.cstr_); 2666 std::swap(index_, other.index_); 2667 } 2668 2669 Value::CZString& Value::CZString::operator=(CZString other) { 2670 swap(other); 2671 return *this; 2672 } 2673 2674 bool Value::CZString::operator<(const CZString& other) const { 2675 if (!cstr_) return index_ < other.index_; 2676 //return strcmp(cstr_, other.cstr_) < 0; 2677 // Assume both are strings. 2678 unsigned this_len = this->storage_.length_; 2679 unsigned other_len = other.storage_.length_; 2680 unsigned min_len = std::min(this_len, other_len); 2681 int comp = memcmp(this->cstr_, other.cstr_, min_len); 2682 if (comp < 0) return true; 2683 if (comp > 0) return false; 2684 return (this_len < other_len); 2685 } 2686 2687 bool Value::CZString::operator==(const CZString& other) const { 2688 if (!cstr_) return index_ == other.index_; 2689 //return strcmp(cstr_, other.cstr_) == 0; 2690 // Assume both are strings. 2691 unsigned this_len = this->storage_.length_; 2692 unsigned other_len = other.storage_.length_; 2693 if (this_len != other_len) return false; 2694 int comp = memcmp(this->cstr_, other.cstr_, this_len); 2695 return comp == 0; 2696 } 2697 2698 ArrayIndex Value::CZString::index() const { return index_; } 2699 2700 //const char* Value::CZString::c_str() const { return cstr_; } 2701 const char* Value::CZString::data() const { return cstr_; } 2702 unsigned Value::CZString::length() const { return storage_.length_; } 2703 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; } 2704 2705 // ////////////////////////////////////////////////////////////////// 2706 // ////////////////////////////////////////////////////////////////// 2707 // ////////////////////////////////////////////////////////////////// 2708 // class Value::Value 2709 // ////////////////////////////////////////////////////////////////// 2710 // ////////////////////////////////////////////////////////////////// 2711 // ////////////////////////////////////////////////////////////////// 2712 2713 /*! \internal Default constructor initialization must be equivalent to: 2714 * memset( this, 0, sizeof(Value) ) 2715 * This optimization is used in ValueInternalMap fast allocator. 2716 */ 2717 Value::Value(ValueType vtype) { 2718 initBasic(vtype); 2719 switch (vtype) { 2720 case nullValue: 2721 break; 2722 case intValue: 2723 case uintValue: 2724 value_.int_ = 0; 2725 break; 2726 case realValue: 2727 value_.real_ = 0.0; 2728 break; 2729 case stringValue: 2730 value_.string_ = 0; 2731 break; 2732 case arrayValue: 2733 case objectValue: 2734 value_.map_ = new ObjectValues(); 2735 break; 2736 case booleanValue: 2737 value_.bool_ = false; 2738 break; 2739 default: 2740 JSON_ASSERT_UNREACHABLE; 2741 } 2742 } 2743 2744 Value::Value(Int value) { 2745 initBasic(intValue); 2746 value_.int_ = value; 2747 } 2748 2749 Value::Value(UInt value) { 2750 initBasic(uintValue); 2751 value_.uint_ = value; 2752 } 2753 #if defined(JSON_HAS_INT64) 2754 Value::Value(Int64 value) { 2755 initBasic(intValue); 2756 value_.int_ = value; 2757 } 2758 Value::Value(UInt64 value) { 2759 initBasic(uintValue); 2760 value_.uint_ = value; 2761 } 2762 #endif // defined(JSON_HAS_INT64) 2763 2764 Value::Value(double value) { 2765 initBasic(realValue); 2766 value_.real_ = value; 2767 } 2768 2769 Value::Value(const char* value) { 2770 initBasic(stringValue, true); 2771 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value))); 2772 } 2773 2774 Value::Value(const char* beginValue, const char* endValue) { 2775 initBasic(stringValue, true); 2776 value_.string_ = 2777 duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue)); 2778 } 2779 2780 Value::Value(const std::string& value) { 2781 initBasic(stringValue, true); 2782 value_.string_ = 2783 duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length())); 2784 } 2785 2786 Value::Value(const StaticString& value) { 2787 initBasic(stringValue); 2788 value_.string_ = const_cast<char*>(value.c_str()); 2789 } 2790 2791 #ifdef JSON_USE_CPPTL 2792 Value::Value(const CppTL::ConstString& value) { 2793 initBasic(stringValue, true); 2794 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length())); 2795 } 2796 #endif 2797 2798 Value::Value(bool value) { 2799 initBasic(booleanValue); 2800 value_.bool_ = value; 2801 } 2802 2803 Value::Value(Value const& other) 2804 : type_(other.type_), allocated_(false) 2805 , 2806 comments_(0), start_(other.start_), limit_(other.limit_) 2807 { 2808 switch (type_) { 2809 case nullValue: 2810 case intValue: 2811 case uintValue: 2812 case realValue: 2813 case booleanValue: 2814 value_ = other.value_; 2815 break; 2816 case stringValue: 2817 if (other.value_.string_ && other.allocated_) { 2818 unsigned len; 2819 char const* str; 2820 decodePrefixedString(other.allocated_, other.value_.string_, 2821 &len, &str); 2822 value_.string_ = duplicateAndPrefixStringValue(str, len); 2823 allocated_ = true; 2824 } else { 2825 value_.string_ = other.value_.string_; 2826 allocated_ = false; 2827 } 2828 break; 2829 case arrayValue: 2830 case objectValue: 2831 value_.map_ = new ObjectValues(*other.value_.map_); 2832 break; 2833 default: 2834 JSON_ASSERT_UNREACHABLE; 2835 } 2836 if (other.comments_) { 2837 comments_ = new CommentInfo[numberOfCommentPlacement]; 2838 for (int comment = 0; comment < numberOfCommentPlacement; ++comment) { 2839 const CommentInfo& otherComment = other.comments_[comment]; 2840 if (otherComment.comment_) 2841 comments_[comment].setComment( 2842 otherComment.comment_, strlen(otherComment.comment_)); 2843 } 2844 } 2845 } 2846 2847 #if JSON_HAS_RVALUE_REFERENCES 2848 // Move constructor 2849 Value::Value(Value&& other) { 2850 initBasic(nullValue); 2851 swap(other); 2852 } 2853 #endif 2854 2855 Value::~Value() { 2856 switch (type_) { 2857 case nullValue: 2858 case intValue: 2859 case uintValue: 2860 case realValue: 2861 case booleanValue: 2862 break; 2863 case stringValue: 2864 if (allocated_) 2865 releaseStringValue(value_.string_); 2866 break; 2867 case arrayValue: 2868 case objectValue: 2869 delete value_.map_; 2870 break; 2871 default: 2872 JSON_ASSERT_UNREACHABLE; 2873 } 2874 2875 if (comments_) 2876 delete[] comments_; 2877 } 2878 2879 Value& Value::operator=(Value other) { 2880 swap(other); 2881 return *this; 2882 } 2883 2884 void Value::swapPayload(Value& other) { 2885 ValueType temp = type_; 2886 type_ = other.type_; 2887 other.type_ = temp; 2888 std::swap(value_, other.value_); 2889 int temp2 = allocated_; 2890 allocated_ = other.allocated_; 2891 other.allocated_ = temp2 & 0x1; 2892 } 2893 2894 void Value::swap(Value& other) { 2895 swapPayload(other); 2896 std::swap(comments_, other.comments_); 2897 std::swap(start_, other.start_); 2898 std::swap(limit_, other.limit_); 2899 } 2900 2901 ValueType Value::type() const { return type_; } 2902 2903 int Value::compare(const Value& other) const { 2904 if (*this < other) 2905 return -1; 2906 if (*this > other) 2907 return 1; 2908 return 0; 2909 } 2910 2911 bool Value::operator<(const Value& other) const { 2912 int typeDelta = type_ - other.type_; 2913 if (typeDelta) 2914 return typeDelta < 0 ? true : false; 2915 switch (type_) { 2916 case nullValue: 2917 return false; 2918 case intValue: 2919 return value_.int_ < other.value_.int_; 2920 case uintValue: 2921 return value_.uint_ < other.value_.uint_; 2922 case realValue: 2923 return value_.real_ < other.value_.real_; 2924 case booleanValue: 2925 return value_.bool_ < other.value_.bool_; 2926 case stringValue: 2927 { 2928 if ((value_.string_ == 0) || (other.value_.string_ == 0)) { 2929 if (other.value_.string_) return true; 2930 else return false; 2931 } 2932 unsigned this_len; 2933 unsigned other_len; 2934 char const* this_str; 2935 char const* other_str; 2936 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 2937 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); 2938 unsigned min_len = std::min(this_len, other_len); 2939 int comp = memcmp(this_str, other_str, min_len); 2940 if (comp < 0) return true; 2941 if (comp > 0) return false; 2942 return (this_len < other_len); 2943 } 2944 case arrayValue: 2945 case objectValue: { 2946 int delta = int(value_.map_->size() - other.value_.map_->size()); 2947 if (delta) 2948 return delta < 0; 2949 return (*value_.map_) < (*other.value_.map_); 2950 } 2951 default: 2952 JSON_ASSERT_UNREACHABLE; 2953 } 2954 return false; // unreachable 2955 } 2956 2957 bool Value::operator<=(const Value& other) const { return !(other < *this); } 2958 2959 bool Value::operator>=(const Value& other) const { return !(*this < other); } 2960 2961 bool Value::operator>(const Value& other) const { return other < *this; } 2962 2963 bool Value::operator==(const Value& other) const { 2964 // if ( type_ != other.type_ ) 2965 // GCC 2.95.3 says: 2966 // attempt to take address of bit-field structure member `Json::Value::type_' 2967 // Beats me, but a temp solves the problem. 2968 int temp = other.type_; 2969 if (type_ != temp) 2970 return false; 2971 switch (type_) { 2972 case nullValue: 2973 return true; 2974 case intValue: 2975 return value_.int_ == other.value_.int_; 2976 case uintValue: 2977 return value_.uint_ == other.value_.uint_; 2978 case realValue: 2979 return value_.real_ == other.value_.real_; 2980 case booleanValue: 2981 return value_.bool_ == other.value_.bool_; 2982 case stringValue: 2983 { 2984 if ((value_.string_ == 0) || (other.value_.string_ == 0)) { 2985 return (value_.string_ == other.value_.string_); 2986 } 2987 unsigned this_len; 2988 unsigned other_len; 2989 char const* this_str; 2990 char const* other_str; 2991 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 2992 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str); 2993 if (this_len != other_len) return false; 2994 int comp = memcmp(this_str, other_str, this_len); 2995 return comp == 0; 2996 } 2997 case arrayValue: 2998 case objectValue: 2999 return value_.map_->size() == other.value_.map_->size() && 3000 (*value_.map_) == (*other.value_.map_); 3001 default: 3002 JSON_ASSERT_UNREACHABLE; 3003 } 3004 return false; // unreachable 3005 } 3006 3007 bool Value::operator!=(const Value& other) const { return !(*this == other); } 3008 3009 const char* Value::asCString() const { 3010 JSON_ASSERT_MESSAGE(type_ == stringValue, 3011 "in Json::Value::asCString(): requires stringValue"); 3012 if (value_.string_ == 0) return 0; 3013 unsigned this_len; 3014 char const* this_str; 3015 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 3016 return this_str; 3017 } 3018 3019 bool Value::getString(char const** str, char const** cend) const { 3020 if (type_ != stringValue) return false; 3021 if (value_.string_ == 0) return false; 3022 unsigned length; 3023 decodePrefixedString(this->allocated_, this->value_.string_, &length, str); 3024 *cend = *str + length; 3025 return true; 3026 } 3027 3028 std::string Value::asString() const { 3029 switch (type_) { 3030 case nullValue: 3031 return ""; 3032 case stringValue: 3033 { 3034 if (value_.string_ == 0) return ""; 3035 unsigned this_len; 3036 char const* this_str; 3037 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str); 3038 return std::string(this_str, this_len); 3039 } 3040 case booleanValue: 3041 return value_.bool_ ? "true" : "false"; 3042 case intValue: 3043 return valueToString(value_.int_); 3044 case uintValue: 3045 return valueToString(value_.uint_); 3046 case realValue: 3047 return valueToString(value_.real_); 3048 default: 3049 JSON_FAIL_MESSAGE("Type is not convertible to string"); 3050 } 3051 } 3052 3053 #ifdef JSON_USE_CPPTL 3054 CppTL::ConstString Value::asConstString() const { 3055 unsigned len; 3056 char const* str; 3057 decodePrefixedString(allocated_, value_.string_, 3058 &len, &str); 3059 return CppTL::ConstString(str, len); 3060 } 3061 #endif 3062 3063 Value::Int Value::asInt() const { 3064 switch (type_) { 3065 case intValue: 3066 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range"); 3067 return Int(value_.int_); 3068 case uintValue: 3069 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range"); 3070 return Int(value_.uint_); 3071 case realValue: 3072 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), 3073 "double out of Int range"); 3074 return Int(value_.real_); 3075 case nullValue: 3076 return 0; 3077 case booleanValue: 3078 return value_.bool_ ? 1 : 0; 3079 default: 3080 break; 3081 } 3082 JSON_FAIL_MESSAGE("Value is not convertible to Int."); 3083 } 3084 3085 Value::UInt Value::asUInt() const { 3086 switch (type_) { 3087 case intValue: 3088 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range"); 3089 return UInt(value_.int_); 3090 case uintValue: 3091 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range"); 3092 return UInt(value_.uint_); 3093 case realValue: 3094 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), 3095 "double out of UInt range"); 3096 return UInt(value_.real_); 3097 case nullValue: 3098 return 0; 3099 case booleanValue: 3100 return value_.bool_ ? 1 : 0; 3101 default: 3102 break; 3103 } 3104 JSON_FAIL_MESSAGE("Value is not convertible to UInt."); 3105 } 3106 3107 #if defined(JSON_HAS_INT64) 3108 3109 Value::Int64 Value::asInt64() const { 3110 switch (type_) { 3111 case intValue: 3112 return Int64(value_.int_); 3113 case uintValue: 3114 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range"); 3115 return Int64(value_.uint_); 3116 case realValue: 3117 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), 3118 "double out of Int64 range"); 3119 return Int64(value_.real_); 3120 case nullValue: 3121 return 0; 3122 case booleanValue: 3123 return value_.bool_ ? 1 : 0; 3124 default: 3125 break; 3126 } 3127 JSON_FAIL_MESSAGE("Value is not convertible to Int64."); 3128 } 3129 3130 Value::UInt64 Value::asUInt64() const { 3131 switch (type_) { 3132 case intValue: 3133 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range"); 3134 return UInt64(value_.int_); 3135 case uintValue: 3136 return UInt64(value_.uint_); 3137 case realValue: 3138 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), 3139 "double out of UInt64 range"); 3140 return UInt64(value_.real_); 3141 case nullValue: 3142 return 0; 3143 case booleanValue: 3144 return value_.bool_ ? 1 : 0; 3145 default: 3146 break; 3147 } 3148 JSON_FAIL_MESSAGE("Value is not convertible to UInt64."); 3149 } 3150 #endif // if defined(JSON_HAS_INT64) 3151 3152 LargestInt Value::asLargestInt() const { 3153 #if defined(JSON_NO_INT64) 3154 return asInt(); 3155 #else 3156 return asInt64(); 3157 #endif 3158 } 3159 3160 LargestUInt Value::asLargestUInt() const { 3161 #if defined(JSON_NO_INT64) 3162 return asUInt(); 3163 #else 3164 return asUInt64(); 3165 #endif 3166 } 3167 3168 double Value::asDouble() const { 3169 switch (type_) { 3170 case intValue: 3171 return static_cast<double>(value_.int_); 3172 case uintValue: 3173 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3174 return static_cast<double>(value_.uint_); 3175 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3176 return integerToDouble(value_.uint_); 3177 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3178 case realValue: 3179 return value_.real_; 3180 case nullValue: 3181 return 0.0; 3182 case booleanValue: 3183 return value_.bool_ ? 1.0 : 0.0; 3184 default: 3185 break; 3186 } 3187 JSON_FAIL_MESSAGE("Value is not convertible to double."); 3188 } 3189 3190 float Value::asFloat() const { 3191 switch (type_) { 3192 case intValue: 3193 return static_cast<float>(value_.int_); 3194 case uintValue: 3195 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3196 return static_cast<float>(value_.uint_); 3197 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3198 return integerToDouble(value_.uint_); 3199 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION) 3200 case realValue: 3201 return static_cast<float>(value_.real_); 3202 case nullValue: 3203 return 0.0; 3204 case booleanValue: 3205 return value_.bool_ ? 1.0f : 0.0f; 3206 default: 3207 break; 3208 } 3209 JSON_FAIL_MESSAGE("Value is not convertible to float."); 3210 } 3211 3212 bool Value::asBool() const { 3213 switch (type_) { 3214 case booleanValue: 3215 return value_.bool_; 3216 case nullValue: 3217 return false; 3218 case intValue: 3219 return value_.int_ ? true : false; 3220 case uintValue: 3221 return value_.uint_ ? true : false; 3222 case realValue: 3223 // This is kind of strange. Not recommended. 3224 return (value_.real_ != 0.0) ? true : false; 3225 default: 3226 break; 3227 } 3228 JSON_FAIL_MESSAGE("Value is not convertible to bool."); 3229 } 3230 3231 bool Value::isConvertibleTo(ValueType other) const { 3232 switch (other) { 3233 case nullValue: 3234 return (isNumeric() && asDouble() == 0.0) || 3235 (type_ == booleanValue && value_.bool_ == false) || 3236 (type_ == stringValue && asString() == "") || 3237 (type_ == arrayValue && value_.map_->size() == 0) || 3238 (type_ == objectValue && value_.map_->size() == 0) || 3239 type_ == nullValue; 3240 case intValue: 3241 return isInt() || 3242 (type_ == realValue && InRange(value_.real_, minInt, maxInt)) || 3243 type_ == booleanValue || type_ == nullValue; 3244 case uintValue: 3245 return isUInt() || 3246 (type_ == realValue && InRange(value_.real_, 0, maxUInt)) || 3247 type_ == booleanValue || type_ == nullValue; 3248 case realValue: 3249 return isNumeric() || type_ == booleanValue || type_ == nullValue; 3250 case booleanValue: 3251 return isNumeric() || type_ == booleanValue || type_ == nullValue; 3252 case stringValue: 3253 return isNumeric() || type_ == booleanValue || type_ == stringValue || 3254 type_ == nullValue; 3255 case arrayValue: 3256 return type_ == arrayValue || type_ == nullValue; 3257 case objectValue: 3258 return type_ == objectValue || type_ == nullValue; 3259 } 3260 JSON_ASSERT_UNREACHABLE; 3261 return false; 3262 } 3263 3264 /// Number of values in array or object 3265 ArrayIndex Value::size() const { 3266 switch (type_) { 3267 case nullValue: 3268 case intValue: 3269 case uintValue: 3270 case realValue: 3271 case booleanValue: 3272 case stringValue: 3273 return 0; 3274 case arrayValue: // size of the array is highest index + 1 3275 if (!value_.map_->empty()) { 3276 ObjectValues::const_iterator itLast = value_.map_->end(); 3277 --itLast; 3278 return (*itLast).first.index() + 1; 3279 } 3280 return 0; 3281 case objectValue: 3282 return ArrayIndex(value_.map_->size()); 3283 } 3284 JSON_ASSERT_UNREACHABLE; 3285 return 0; // unreachable; 3286 } 3287 3288 bool Value::empty() const { 3289 if (isNull() || isArray() || isObject()) 3290 return size() == 0u; 3291 else 3292 return false; 3293 } 3294 3295 bool Value::operator!() const { return isNull(); } 3296 3297 void Value::clear() { 3298 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || 3299 type_ == objectValue, 3300 "in Json::Value::clear(): requires complex value"); 3301 start_ = 0; 3302 limit_ = 0; 3303 switch (type_) { 3304 case arrayValue: 3305 case objectValue: 3306 value_.map_->clear(); 3307 break; 3308 default: 3309 break; 3310 } 3311 } 3312 3313 void Value::resize(ArrayIndex newSize) { 3314 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue, 3315 "in Json::Value::resize(): requires arrayValue"); 3316 if (type_ == nullValue) 3317 *this = Value(arrayValue); 3318 ArrayIndex oldSize = size(); 3319 if (newSize == 0) 3320 clear(); 3321 else if (newSize > oldSize) 3322 (*this)[newSize - 1]; 3323 else { 3324 for (ArrayIndex index = newSize; index < oldSize; ++index) { 3325 value_.map_->erase(index); 3326 } 3327 assert(size() == newSize); 3328 } 3329 } 3330 3331 Value& Value::operator[](ArrayIndex index) { 3332 JSON_ASSERT_MESSAGE( 3333 type_ == nullValue || type_ == arrayValue, 3334 "in Json::Value::operator[](ArrayIndex): requires arrayValue"); 3335 if (type_ == nullValue) 3336 *this = Value(arrayValue); 3337 CZString key(index); 3338 ObjectValues::iterator it = value_.map_->lower_bound(key); 3339 if (it != value_.map_->end() && (*it).first == key) 3340 return (*it).second; 3341 3342 ObjectValues::value_type defaultValue(key, nullRef); 3343 it = value_.map_->insert(it, defaultValue); 3344 return (*it).second; 3345 } 3346 3347 Value& Value::operator[](int index) { 3348 JSON_ASSERT_MESSAGE( 3349 index >= 0, 3350 "in Json::Value::operator[](int index): index cannot be negative"); 3351 return (*this)[ArrayIndex(index)]; 3352 } 3353 3354 const Value& Value::operator[](ArrayIndex index) const { 3355 JSON_ASSERT_MESSAGE( 3356 type_ == nullValue || type_ == arrayValue, 3357 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue"); 3358 if (type_ == nullValue) 3359 return nullRef; 3360 CZString key(index); 3361 ObjectValues::const_iterator it = value_.map_->find(key); 3362 if (it == value_.map_->end()) 3363 return nullRef; 3364 return (*it).second; 3365 } 3366 3367 const Value& Value::operator[](int index) const { 3368 JSON_ASSERT_MESSAGE( 3369 index >= 0, 3370 "in Json::Value::operator[](int index) const: index cannot be negative"); 3371 return (*this)[ArrayIndex(index)]; 3372 } 3373 3374 void Value::initBasic(ValueType vtype, bool allocated) { 3375 type_ = vtype; 3376 allocated_ = allocated; 3377 comments_ = 0; 3378 start_ = 0; 3379 limit_ = 0; 3380 } 3381 3382 // Access an object value by name, create a null member if it does not exist. 3383 // @pre Type of '*this' is object or null. 3384 // @param key is null-terminated. 3385 Value& Value::resolveReference(const char* key) { 3386 JSON_ASSERT_MESSAGE( 3387 type_ == nullValue || type_ == objectValue, 3388 "in Json::Value::resolveReference(): requires objectValue"); 3389 if (type_ == nullValue) 3390 *this = Value(objectValue); 3391 CZString actualKey( 3392 key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE! 3393 ObjectValues::iterator it = value_.map_->lower_bound(actualKey); 3394 if (it != value_.map_->end() && (*it).first == actualKey) 3395 return (*it).second; 3396 3397 ObjectValues::value_type defaultValue(actualKey, nullRef); 3398 it = value_.map_->insert(it, defaultValue); 3399 Value& value = (*it).second; 3400 return value; 3401 } 3402 3403 // @param key is not null-terminated. 3404 Value& Value::resolveReference(char const* key, char const* cend) 3405 { 3406 JSON_ASSERT_MESSAGE( 3407 type_ == nullValue || type_ == objectValue, 3408 "in Json::Value::resolveReference(key, end): requires objectValue"); 3409 if (type_ == nullValue) 3410 *this = Value(objectValue); 3411 CZString actualKey( 3412 key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy); 3413 ObjectValues::iterator it = value_.map_->lower_bound(actualKey); 3414 if (it != value_.map_->end() && (*it).first == actualKey) 3415 return (*it).second; 3416 3417 ObjectValues::value_type defaultValue(actualKey, nullRef); 3418 it = value_.map_->insert(it, defaultValue); 3419 Value& value = (*it).second; 3420 return value; 3421 } 3422 3423 Value Value::get(ArrayIndex index, const Value& defaultValue) const { 3424 const Value* value = &((*this)[index]); 3425 return value == &nullRef ? defaultValue : *value; 3426 } 3427 3428 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); } 3429 3430 Value const* Value::find(char const* key, char const* cend) const 3431 { 3432 JSON_ASSERT_MESSAGE( 3433 type_ == nullValue || type_ == objectValue, 3434 "in Json::Value::find(key, end, found): requires objectValue or nullValue"); 3435 if (type_ == nullValue) return NULL; 3436 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); 3437 ObjectValues::const_iterator it = value_.map_->find(actualKey); 3438 if (it == value_.map_->end()) return NULL; 3439 return &(*it).second; 3440 } 3441 const Value& Value::operator[](const char* key) const 3442 { 3443 Value const* found = find(key, key + strlen(key)); 3444 if (!found) return nullRef; 3445 return *found; 3446 } 3447 Value const& Value::operator[](std::string const& key) const 3448 { 3449 Value const* found = find(key.data(), key.data() + key.length()); 3450 if (!found) return nullRef; 3451 return *found; 3452 } 3453 3454 Value& Value::operator[](const char* key) { 3455 return resolveReference(key, key + strlen(key)); 3456 } 3457 3458 Value& Value::operator[](const std::string& key) { 3459 return resolveReference(key.data(), key.data() + key.length()); 3460 } 3461 3462 Value& Value::operator[](const StaticString& key) { 3463 return resolveReference(key.c_str()); 3464 } 3465 3466 #ifdef JSON_USE_CPPTL 3467 Value& Value::operator[](const CppTL::ConstString& key) { 3468 return resolveReference(key.c_str(), key.end_c_str()); 3469 } 3470 Value const& Value::operator[](CppTL::ConstString const& key) const 3471 { 3472 Value const* found = find(key.c_str(), key.end_c_str()); 3473 if (!found) return nullRef; 3474 return *found; 3475 } 3476 #endif 3477 3478 Value& Value::append(const Value& value) { return (*this)[size()] = value; } 3479 3480 Value Value::get(char const* key, char const* cend, Value const& defaultValue) const 3481 { 3482 Value const* found = find(key, cend); 3483 return !found ? defaultValue : *found; 3484 } 3485 Value Value::get(char const* key, Value const& defaultValue) const 3486 { 3487 return get(key, key + strlen(key), defaultValue); 3488 } 3489 Value Value::get(std::string const& key, Value const& defaultValue) const 3490 { 3491 return get(key.data(), key.data() + key.length(), defaultValue); 3492 } 3493 3494 3495 bool Value::removeMember(const char* key, const char* cend, Value* removed) 3496 { 3497 if (type_ != objectValue) { 3498 return false; 3499 } 3500 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication); 3501 ObjectValues::iterator it = value_.map_->find(actualKey); 3502 if (it == value_.map_->end()) 3503 return false; 3504 *removed = it->second; 3505 value_.map_->erase(it); 3506 return true; 3507 } 3508 bool Value::removeMember(const char* key, Value* removed) 3509 { 3510 return removeMember(key, key + strlen(key), removed); 3511 } 3512 bool Value::removeMember(std::string const& key, Value* removed) 3513 { 3514 return removeMember(key.data(), key.data() + key.length(), removed); 3515 } 3516 Value Value::removeMember(const char* key) 3517 { 3518 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue, 3519 "in Json::Value::removeMember(): requires objectValue"); 3520 if (type_ == nullValue) 3521 return nullRef; 3522 3523 Value removed; // null 3524 removeMember(key, key + strlen(key), &removed); 3525 return removed; // still null if removeMember() did nothing 3526 } 3527 Value Value::removeMember(const std::string& key) 3528 { 3529 return removeMember(key.c_str()); 3530 } 3531 3532 bool Value::removeIndex(ArrayIndex index, Value* removed) { 3533 if (type_ != arrayValue) { 3534 return false; 3535 } 3536 CZString key(index); 3537 ObjectValues::iterator it = value_.map_->find(key); 3538 if (it == value_.map_->end()) { 3539 return false; 3540 } 3541 *removed = it->second; 3542 ArrayIndex oldSize = size(); 3543 // shift left all items left, into the place of the "removed" 3544 for (ArrayIndex i = index; i < (oldSize - 1); ++i){ 3545 CZString keey(i); 3546 (*value_.map_)[keey] = (*this)[i + 1]; 3547 } 3548 // erase the last one ("leftover") 3549 CZString keyLast(oldSize - 1); 3550 ObjectValues::iterator itLast = value_.map_->find(keyLast); 3551 value_.map_->erase(itLast); 3552 return true; 3553 } 3554 3555 #ifdef JSON_USE_CPPTL 3556 Value Value::get(const CppTL::ConstString& key, 3557 const Value& defaultValue) const { 3558 return get(key.c_str(), key.end_c_str(), defaultValue); 3559 } 3560 #endif 3561 3562 bool Value::isMember(char const* key, char const* cend) const 3563 { 3564 Value const* value = find(key, cend); 3565 return NULL != value; 3566 } 3567 bool Value::isMember(char const* key) const 3568 { 3569 return isMember(key, key + strlen(key)); 3570 } 3571 bool Value::isMember(std::string const& key) const 3572 { 3573 return isMember(key.data(), key.data() + key.length()); 3574 } 3575 3576 #ifdef JSON_USE_CPPTL 3577 bool Value::isMember(const CppTL::ConstString& key) const { 3578 return isMember(key.c_str(), key.end_c_str()); 3579 } 3580 #endif 3581 3582 Value::Members Value::getMemberNames() const { 3583 JSON_ASSERT_MESSAGE( 3584 type_ == nullValue || type_ == objectValue, 3585 "in Json::Value::getMemberNames(), value must be objectValue"); 3586 if (type_ == nullValue) 3587 return Value::Members(); 3588 Members members; 3589 members.reserve(value_.map_->size()); 3590 ObjectValues::const_iterator it = value_.map_->begin(); 3591 ObjectValues::const_iterator itEnd = value_.map_->end(); 3592 for (; it != itEnd; ++it) { 3593 members.push_back(std::string((*it).first.data(), 3594 (*it).first.length())); 3595 } 3596 return members; 3597 } 3598 // 3599 //# ifdef JSON_USE_CPPTL 3600 // EnumMemberNames 3601 // Value::enumMemberNames() const 3602 //{ 3603 // if ( type_ == objectValue ) 3604 // { 3605 // return CppTL::Enum::any( CppTL::Enum::transform( 3606 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ), 3607 // MemberNamesTransform() ) ); 3608 // } 3609 // return EnumMemberNames(); 3610 //} 3611 // 3612 // 3613 // EnumValues 3614 // Value::enumValues() const 3615 //{ 3616 // if ( type_ == objectValue || type_ == arrayValue ) 3617 // return CppTL::Enum::anyValues( *(value_.map_), 3618 // CppTL::Type<const Value &>() ); 3619 // return EnumValues(); 3620 //} 3621 // 3622 //# endif 3623 3624 static bool IsIntegral(double d) { 3625 double integral_part; 3626 return modf(d, &integral_part) == 0.0; 3627 } 3628 3629 bool Value::isNull() const { return type_ == nullValue; } 3630 3631 bool Value::isBool() const { return type_ == booleanValue; } 3632 3633 bool Value::isInt() const { 3634 switch (type_) { 3635 case intValue: 3636 return value_.int_ >= minInt && value_.int_ <= maxInt; 3637 case uintValue: 3638 return value_.uint_ <= UInt(maxInt); 3639 case realValue: 3640 return value_.real_ >= minInt && value_.real_ <= maxInt && 3641 IsIntegral(value_.real_); 3642 default: 3643 break; 3644 } 3645 return false; 3646 } 3647 3648 bool Value::isUInt() const { 3649 switch (type_) { 3650 case intValue: 3651 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt); 3652 case uintValue: 3653 return value_.uint_ <= maxUInt; 3654 case realValue: 3655 return value_.real_ >= 0 && value_.real_ <= maxUInt && 3656 IsIntegral(value_.real_); 3657 default: 3658 break; 3659 } 3660 return false; 3661 } 3662 3663 bool Value::isInt64() const { 3664 #if defined(JSON_HAS_INT64) 3665 switch (type_) { 3666 case intValue: 3667 return true; 3668 case uintValue: 3669 return value_.uint_ <= UInt64(maxInt64); 3670 case realValue: 3671 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a 3672 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we 3673 // require the value to be strictly less than the limit. 3674 return value_.real_ >= double(minInt64) && 3675 value_.real_ < double(maxInt64) && IsIntegral(value_.real_); 3676 default: 3677 break; 3678 } 3679 #endif // JSON_HAS_INT64 3680 return false; 3681 } 3682 3683 bool Value::isUInt64() const { 3684 #if defined(JSON_HAS_INT64) 3685 switch (type_) { 3686 case intValue: 3687 return value_.int_ >= 0; 3688 case uintValue: 3689 return true; 3690 case realValue: 3691 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a 3692 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we 3693 // require the value to be strictly less than the limit. 3694 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && 3695 IsIntegral(value_.real_); 3696 default: 3697 break; 3698 } 3699 #endif // JSON_HAS_INT64 3700 return false; 3701 } 3702 3703 bool Value::isIntegral() const { 3704 #if defined(JSON_HAS_INT64) 3705 return isInt64() || isUInt64(); 3706 #else 3707 return isInt() || isUInt(); 3708 #endif 3709 } 3710 3711 bool Value::isDouble() const { return type_ == realValue || isIntegral(); } 3712 3713 bool Value::isNumeric() const { return isIntegral() || isDouble(); } 3714 3715 bool Value::isString() const { return type_ == stringValue; } 3716 3717 bool Value::isArray() const { return type_ == arrayValue; } 3718 3719 bool Value::isObject() const { return type_ == objectValue; } 3720 3721 void Value::setComment(const char* comment, size_t len, CommentPlacement placement) { 3722 if (!comments_) 3723 comments_ = new CommentInfo[numberOfCommentPlacement]; 3724 if ((len > 0) && (comment[len-1] == '\n')) { 3725 // Always discard trailing newline, to aid indentation. 3726 len -= 1; 3727 } 3728 comments_[placement].setComment(comment, len); 3729 } 3730 3731 void Value::setComment(const char* comment, CommentPlacement placement) { 3732 setComment(comment, strlen(comment), placement); 3733 } 3734 3735 void Value::setComment(const std::string& comment, CommentPlacement placement) { 3736 setComment(comment.c_str(), comment.length(), placement); 3737 } 3738 3739 bool Value::hasComment(CommentPlacement placement) const { 3740 return comments_ != 0 && comments_[placement].comment_ != 0; 3741 } 3742 3743 std::string Value::getComment(CommentPlacement placement) const { 3744 if (hasComment(placement)) 3745 return comments_[placement].comment_; 3746 return ""; 3747 } 3748 3749 void Value::setOffsetStart(size_t start) { start_ = start; } 3750 3751 void Value::setOffsetLimit(size_t limit) { limit_ = limit; } 3752 3753 size_t Value::getOffsetStart() const { return start_; } 3754 3755 size_t Value::getOffsetLimit() const { return limit_; } 3756 3757 std::string Value::toStyledString() const { 3758 StyledWriter writer; 3759 return writer.write(*this); 3760 } 3761 3762 Value::const_iterator Value::begin() const { 3763 switch (type_) { 3764 case arrayValue: 3765 case objectValue: 3766 if (value_.map_) 3767 return const_iterator(value_.map_->begin()); 3768 break; 3769 default: 3770 break; 3771 } 3772 return const_iterator(); 3773 } 3774 3775 Value::const_iterator Value::end() const { 3776 switch (type_) { 3777 case arrayValue: 3778 case objectValue: 3779 if (value_.map_) 3780 return const_iterator(value_.map_->end()); 3781 break; 3782 default: 3783 break; 3784 } 3785 return const_iterator(); 3786 } 3787 3788 Value::iterator Value::begin() { 3789 switch (type_) { 3790 case arrayValue: 3791 case objectValue: 3792 if (value_.map_) 3793 return iterator(value_.map_->begin()); 3794 break; 3795 default: 3796 break; 3797 } 3798 return iterator(); 3799 } 3800 3801 Value::iterator Value::end() { 3802 switch (type_) { 3803 case arrayValue: 3804 case objectValue: 3805 if (value_.map_) 3806 return iterator(value_.map_->end()); 3807 break; 3808 default: 3809 break; 3810 } 3811 return iterator(); 3812 } 3813 3814 // class PathArgument 3815 // ////////////////////////////////////////////////////////////////// 3816 3817 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {} 3818 3819 PathArgument::PathArgument(ArrayIndex index) 3820 : key_(), index_(index), kind_(kindIndex) {} 3821 3822 PathArgument::PathArgument(const char* key) 3823 : key_(key), index_(), kind_(kindKey) {} 3824 3825 PathArgument::PathArgument(const std::string& key) 3826 : key_(key.c_str()), index_(), kind_(kindKey) {} 3827 3828 // class Path 3829 // ////////////////////////////////////////////////////////////////// 3830 3831 Path::Path(const std::string& path, 3832 const PathArgument& a1, 3833 const PathArgument& a2, 3834 const PathArgument& a3, 3835 const PathArgument& a4, 3836 const PathArgument& a5) { 3837 InArgs in; 3838 in.push_back(&a1); 3839 in.push_back(&a2); 3840 in.push_back(&a3); 3841 in.push_back(&a4); 3842 in.push_back(&a5); 3843 makePath(path, in); 3844 } 3845 3846 void Path::makePath(const std::string& path, const InArgs& in) { 3847 const char* current = path.c_str(); 3848 const char* end = current + path.length(); 3849 InArgs::const_iterator itInArg = in.begin(); 3850 while (current != end) { 3851 if (*current == '[') { 3852 ++current; 3853 if (*current == '%') 3854 addPathInArg(path, in, itInArg, PathArgument::kindIndex); 3855 else { 3856 ArrayIndex index = 0; 3857 for (; current != end && *current >= '0' && *current <= '9'; ++current) 3858 index = index * 10 + ArrayIndex(*current - '0'); 3859 args_.push_back(index); 3860 } 3861 if (current == end || *current++ != ']') 3862 invalidPath(path, int(current - path.c_str())); 3863 } else if (*current == '%') { 3864 addPathInArg(path, in, itInArg, PathArgument::kindKey); 3865 ++current; 3866 } else if (*current == '.') { 3867 ++current; 3868 } else { 3869 const char* beginName = current; 3870 while (current != end && !strchr("[.", *current)) 3871 ++current; 3872 args_.push_back(std::string(beginName, current)); 3873 } 3874 } 3875 } 3876 3877 void Path::addPathInArg(const std::string& /*path*/, 3878 const InArgs& in, 3879 InArgs::const_iterator& itInArg, 3880 PathArgument::Kind kind) { 3881 if (itInArg == in.end()) { 3882 // Error: missing argument %d 3883 } else if ((*itInArg)->kind_ != kind) { 3884 // Error: bad argument type 3885 } else { 3886 args_.push_back(**itInArg); 3887 } 3888 } 3889 3890 void Path::invalidPath(const std::string& /*path*/, int /*location*/) { 3891 // Error: invalid path. 3892 } 3893 3894 const Value& Path::resolve(const Value& root) const { 3895 const Value* node = &root; 3896 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3897 const PathArgument& arg = *it; 3898 if (arg.kind_ == PathArgument::kindIndex) { 3899 if (!node->isArray() || !node->isValidIndex(arg.index_)) { 3900 // Error: unable to resolve path (array value expected at position... 3901 } 3902 node = &((*node)[arg.index_]); 3903 } else if (arg.kind_ == PathArgument::kindKey) { 3904 if (!node->isObject()) { 3905 // Error: unable to resolve path (object value expected at position...) 3906 } 3907 node = &((*node)[arg.key_]); 3908 if (node == &Value::nullRef) { 3909 // Error: unable to resolve path (object has no member named '' at 3910 // position...) 3911 } 3912 } 3913 } 3914 return *node; 3915 } 3916 3917 Value Path::resolve(const Value& root, const Value& defaultValue) const { 3918 const Value* node = &root; 3919 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3920 const PathArgument& arg = *it; 3921 if (arg.kind_ == PathArgument::kindIndex) { 3922 if (!node->isArray() || !node->isValidIndex(arg.index_)) 3923 return defaultValue; 3924 node = &((*node)[arg.index_]); 3925 } else if (arg.kind_ == PathArgument::kindKey) { 3926 if (!node->isObject()) 3927 return defaultValue; 3928 node = &((*node)[arg.key_]); 3929 if (node == &Value::nullRef) 3930 return defaultValue; 3931 } 3932 } 3933 return *node; 3934 } 3935 3936 Value& Path::make(Value& root) const { 3937 Value* node = &root; 3938 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) { 3939 const PathArgument& arg = *it; 3940 if (arg.kind_ == PathArgument::kindIndex) { 3941 if (!node->isArray()) { 3942 // Error: node is not an array at position ... 3943 } 3944 node = &((*node)[arg.index_]); 3945 } else if (arg.kind_ == PathArgument::kindKey) { 3946 if (!node->isObject()) { 3947 // Error: node is not an object at position... 3948 } 3949 node = &((*node)[arg.key_]); 3950 } 3951 } 3952 return *node; 3953 } 3954 3955 } // namespace Json 3956 3957 // ////////////////////////////////////////////////////////////////////// 3958 // End of content of file: src/lib_json/json_value.cpp 3959 // ////////////////////////////////////////////////////////////////////// 3960 3961 3962 3963 3964 3965 3966 // ////////////////////////////////////////////////////////////////////// 3967 // Beginning of content of file: src/lib_json/json_writer.cpp 3968 // ////////////////////////////////////////////////////////////////////// 3969 3970 // Copyright 2011 Baptiste Lepilleur 3971 // Distributed under MIT license, or public domain if desired and 3972 // recognized in your jurisdiction. 3973 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE 3974 3975 #if !defined(JSON_IS_AMALGAMATION) 3976 #include <json/writer.h> 3977 #include "json_tool.h" 3978 #endif // if !defined(JSON_IS_AMALGAMATION) 3979 #include <iomanip> 3980 #include <memory> 3981 #include <sstream> 3982 #include <utility> 3983 #include <set> 3984 #include <cassert> 3985 #include <cstring> 3986 #include <cstdio> 3987 3988 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0 3989 #include <float.h> 3990 #define isfinite _finite 3991 #elif defined(__sun) && defined(__SVR4) //Solaris 3992 #if !defined(isfinite) 3993 #include <ieeefp.h> 3994 #define isfinite finite 3995 #endif 3996 #elif defined(_AIX) 3997 #if !defined(isfinite) 3998 #include <math.h> 3999 #define isfinite finite 4000 #endif 4001 #elif defined(__hpux) 4002 #if !defined(isfinite) 4003 #if defined(__ia64) && !defined(finite) 4004 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \ 4005 _Isfinitef(x) : _IsFinite(x))) 4006 #else 4007 #include <math.h> 4008 #define isfinite finite 4009 #endif 4010 #endif 4011 #else 4012 #include <cmath> 4013 #if !(defined(__QNXNTO__)) // QNX already defines isfinite 4014 #define isfinite std::isfinite 4015 #endif 4016 #endif 4017 4018 #if defined(_MSC_VER) 4019 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 4020 #define snprintf sprintf_s 4021 #elif _MSC_VER >= 1900 // VC++ 14.0 and above 4022 #define snprintf std::snprintf 4023 #else 4024 #define snprintf _snprintf 4025 #endif 4026 #elif defined(__ANDROID__) || defined(__QNXNTO__) 4027 #define snprintf snprintf 4028 #elif __cplusplus >= 201103L 4029 #define snprintf std::snprintf 4030 #endif 4031 4032 #if defined(__BORLANDC__) 4033 #include <float.h> 4034 #define isfinite _finite 4035 #define snprintf _snprintf 4036 #endif 4037 4038 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0 4039 // Disable warning about strdup being deprecated. 4040 #pragma warning(disable : 4996) 4041 #endif 4042 4043 namespace Json { 4044 4045 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 4046 typedef std::unique_ptr<StreamWriter> StreamWriterPtr; 4047 #else 4048 typedef std::auto_ptr<StreamWriter> StreamWriterPtr; 4049 #endif 4050 4051 static bool containsControlCharacter(const char* str) { 4052 while (*str) { 4053 if (isControlCharacter(*(str++))) 4054 return true; 4055 } 4056 return false; 4057 } 4058 4059 static bool containsControlCharacter0(const char* str, unsigned len) { 4060 char const* end = str + len; 4061 while (end != str) { 4062 if (isControlCharacter(*str) || 0==*str) 4063 return true; 4064 ++str; 4065 } 4066 return false; 4067 } 4068 4069 std::string valueToString(LargestInt value) { 4070 UIntToStringBuffer buffer; 4071 char* current = buffer + sizeof(buffer); 4072 if (value == Value::minLargestInt) { 4073 uintToString(LargestUInt(Value::maxLargestInt) + 1, current); 4074 *--current = '-'; 4075 } else if (value < 0) { 4076 uintToString(LargestUInt(-value), current); 4077 *--current = '-'; 4078 } else { 4079 uintToString(LargestUInt(value), current); 4080 } 4081 assert(current >= buffer); 4082 return current; 4083 } 4084 4085 std::string valueToString(LargestUInt value) { 4086 UIntToStringBuffer buffer; 4087 char* current = buffer + sizeof(buffer); 4088 uintToString(value, current); 4089 assert(current >= buffer); 4090 return current; 4091 } 4092 4093 #if defined(JSON_HAS_INT64) 4094 4095 std::string valueToString(Int value) { 4096 return valueToString(LargestInt(value)); 4097 } 4098 4099 std::string valueToString(UInt value) { 4100 return valueToString(LargestUInt(value)); 4101 } 4102 4103 #endif // # if defined(JSON_HAS_INT64) 4104 4105 std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) { 4106 // Allocate a buffer that is more than large enough to store the 16 digits of 4107 // precision requested below. 4108 char buffer[32]; 4109 int len = -1; 4110 4111 char formatString[6]; 4112 sprintf(formatString, "%%.%dg", precision); 4113 4114 // Print into the buffer. We need not request the alternative representation 4115 // that always has a decimal point because JSON doesn't distingish the 4116 // concepts of reals and integers. 4117 if (isfinite(value)) { 4118 len = snprintf(buffer, sizeof(buffer), formatString, value); 4119 } else { 4120 // IEEE standard states that NaN values will not compare to themselves 4121 if (value != value) { 4122 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null"); 4123 } else if (value < 0) { 4124 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999"); 4125 } else { 4126 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999"); 4127 } 4128 // For those, we do not need to call fixNumLoc, but it is fast. 4129 } 4130 assert(len >= 0); 4131 fixNumericLocale(buffer, buffer + len); 4132 return buffer; 4133 } 4134 4135 std::string valueToString(double value) { return valueToString(value, false, 17); } 4136 4137 std::string valueToString(bool value) { return value ? "true" : "false"; } 4138 4139 std::string valueToQuotedString(const char* value) { 4140 if (value == NULL) 4141 return ""; 4142 // Not sure how to handle unicode... 4143 if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && 4144 !containsControlCharacter(value)) 4145 return std::string("\"") + value + "\""; 4146 // We have to walk value and escape any special characters. 4147 // Appending to std::string is not efficient, but this should be rare. 4148 // (Note: forward slashes are *not* rare, but I am not escaping them.) 4149 std::string::size_type maxsize = 4150 strlen(value) * 2 + 3; // allescaped+quotes+NULL 4151 std::string result; 4152 result.reserve(maxsize); // to avoid lots of mallocs 4153 result += "\""; 4154 for (const char* c = value; *c != 0; ++c) { 4155 switch (*c) { 4156 case '\"': 4157 result += "\\\""; 4158 break; 4159 case '\\': 4160 result += "\\\\"; 4161 break; 4162 case '\b': 4163 result += "\\b"; 4164 break; 4165 case '\f': 4166 result += "\\f"; 4167 break; 4168 case '\n': 4169 result += "\\n"; 4170 break; 4171 case '\r': 4172 result += "\\r"; 4173 break; 4174 case '\t': 4175 result += "\\t"; 4176 break; 4177 // case '/': 4178 // Even though \/ is considered a legal escape in JSON, a bare 4179 // slash is also legal, so I see no reason to escape it. 4180 // (I hope I am not misunderstanding something. 4181 // blep notes: actually escaping \/ may be useful in javascript to avoid </ 4182 // sequence. 4183 // Should add a flag to allow this compatibility mode and prevent this 4184 // sequence from occurring. 4185 default: 4186 if (isControlCharacter(*c)) { 4187 std::ostringstream oss; 4188 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') 4189 << std::setw(4) << static_cast<int>(*c); 4190 result += oss.str(); 4191 } else { 4192 result += *c; 4193 } 4194 break; 4195 } 4196 } 4197 result += "\""; 4198 return result; 4199 } 4200 4201 // https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp 4202 static char const* strnpbrk(char const* s, char const* accept, size_t n) { 4203 assert((s || !n) && accept); 4204 4205 char const* const end = s + n; 4206 for (char const* cur = s; cur < end; ++cur) { 4207 int const c = *cur; 4208 for (char const* a = accept; *a; ++a) { 4209 if (*a == c) { 4210 return cur; 4211 } 4212 } 4213 } 4214 return NULL; 4215 } 4216 static std::string valueToQuotedStringN(const char* value, unsigned length) { 4217 if (value == NULL) 4218 return ""; 4219 // Not sure how to handle unicode... 4220 if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && 4221 !containsControlCharacter0(value, length)) 4222 return std::string("\"") + value + "\""; 4223 // We have to walk value and escape any special characters. 4224 // Appending to std::string is not efficient, but this should be rare. 4225 // (Note: forward slashes are *not* rare, but I am not escaping them.) 4226 std::string::size_type maxsize = 4227 length * 2 + 3; // allescaped+quotes+NULL 4228 std::string result; 4229 result.reserve(maxsize); // to avoid lots of mallocs 4230 result += "\""; 4231 char const* end = value + length; 4232 for (const char* c = value; c != end; ++c) { 4233 switch (*c) { 4234 case '\"': 4235 result += "\\\""; 4236 break; 4237 case '\\': 4238 result += "\\\\"; 4239 break; 4240 case '\b': 4241 result += "\\b"; 4242 break; 4243 case '\f': 4244 result += "\\f"; 4245 break; 4246 case '\n': 4247 result += "\\n"; 4248 break; 4249 case '\r': 4250 result += "\\r"; 4251 break; 4252 case '\t': 4253 result += "\\t"; 4254 break; 4255 // case '/': 4256 // Even though \/ is considered a legal escape in JSON, a bare 4257 // slash is also legal, so I see no reason to escape it. 4258 // (I hope I am not misunderstanding something.) 4259 // blep notes: actually escaping \/ may be useful in javascript to avoid </ 4260 // sequence. 4261 // Should add a flag to allow this compatibility mode and prevent this 4262 // sequence from occurring. 4263 default: 4264 if ((isControlCharacter(*c)) || (*c == 0)) { 4265 std::ostringstream oss; 4266 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') 4267 << std::setw(4) << static_cast<int>(*c); 4268 result += oss.str(); 4269 } else { 4270 result += *c; 4271 } 4272 break; 4273 } 4274 } 4275 result += "\""; 4276 return result; 4277 } 4278 4279 // Class Writer 4280 // ////////////////////////////////////////////////////////////////// 4281 Writer::~Writer() {} 4282 4283 // Class FastWriter 4284 // ////////////////////////////////////////////////////////////////// 4285 4286 FastWriter::FastWriter() 4287 : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), 4288 omitEndingLineFeed_(false) {} 4289 4290 void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } 4291 4292 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } 4293 4294 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; } 4295 4296 std::string FastWriter::write(const Value& root) { 4297 document_ = ""; 4298 writeValue(root); 4299 if (!omitEndingLineFeed_) 4300 document_ += "\n"; 4301 return document_; 4302 } 4303 4304 void FastWriter::writeValue(const Value& value) { 4305 switch (value.type()) { 4306 case nullValue: 4307 if (!dropNullPlaceholders_) 4308 document_ += "null"; 4309 break; 4310 case intValue: 4311 document_ += valueToString(value.asLargestInt()); 4312 break; 4313 case uintValue: 4314 document_ += valueToString(value.asLargestUInt()); 4315 break; 4316 case realValue: 4317 document_ += valueToString(value.asDouble()); 4318 break; 4319 case stringValue: 4320 { 4321 // Is NULL possible for value.string_? 4322 char const* str; 4323 char const* end; 4324 bool ok = value.getString(&str, &end); 4325 if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str)); 4326 break; 4327 } 4328 case booleanValue: 4329 document_ += valueToString(value.asBool()); 4330 break; 4331 case arrayValue: { 4332 document_ += '['; 4333 int size = value.size(); 4334 for (int index = 0; index < size; ++index) { 4335 if (index > 0) 4336 document_ += ','; 4337 writeValue(value[index]); 4338 } 4339 document_ += ']'; 4340 } break; 4341 case objectValue: { 4342 Value::Members members(value.getMemberNames()); 4343 document_ += '{'; 4344 for (Value::Members::iterator it = members.begin(); it != members.end(); 4345 ++it) { 4346 const std::string& name = *it; 4347 if (it != members.begin()) 4348 document_ += ','; 4349 document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())); 4350 document_ += yamlCompatiblityEnabled_ ? ": " : ":"; 4351 writeValue(value[name]); 4352 } 4353 document_ += '}'; 4354 } break; 4355 } 4356 } 4357 4358 // Class StyledWriter 4359 // ////////////////////////////////////////////////////////////////// 4360 4361 StyledWriter::StyledWriter() 4362 : rightMargin_(74), indentSize_(3), addChildValues_() {} 4363 4364 std::string StyledWriter::write(const Value& root) { 4365 document_ = ""; 4366 addChildValues_ = false; 4367 indentString_ = ""; 4368 writeCommentBeforeValue(root); 4369 writeValue(root); 4370 writeCommentAfterValueOnSameLine(root); 4371 document_ += "\n"; 4372 return document_; 4373 } 4374 4375 void StyledWriter::writeValue(const Value& value) { 4376 switch (value.type()) { 4377 case nullValue: 4378 pushValue("null"); 4379 break; 4380 case intValue: 4381 pushValue(valueToString(value.asLargestInt())); 4382 break; 4383 case uintValue: 4384 pushValue(valueToString(value.asLargestUInt())); 4385 break; 4386 case realValue: 4387 pushValue(valueToString(value.asDouble())); 4388 break; 4389 case stringValue: 4390 { 4391 // Is NULL possible for value.string_? 4392 char const* str; 4393 char const* end; 4394 bool ok = value.getString(&str, &end); 4395 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4396 else pushValue(""); 4397 break; 4398 } 4399 case booleanValue: 4400 pushValue(valueToString(value.asBool())); 4401 break; 4402 case arrayValue: 4403 writeArrayValue(value); 4404 break; 4405 case objectValue: { 4406 Value::Members members(value.getMemberNames()); 4407 if (members.empty()) 4408 pushValue("{}"); 4409 else { 4410 writeWithIndent("{"); 4411 indent(); 4412 Value::Members::iterator it = members.begin(); 4413 for (;;) { 4414 const std::string& name = *it; 4415 const Value& childValue = value[name]; 4416 writeCommentBeforeValue(childValue); 4417 writeWithIndent(valueToQuotedString(name.c_str())); 4418 document_ += " : "; 4419 writeValue(childValue); 4420 if (++it == members.end()) { 4421 writeCommentAfterValueOnSameLine(childValue); 4422 break; 4423 } 4424 document_ += ','; 4425 writeCommentAfterValueOnSameLine(childValue); 4426 } 4427 unindent(); 4428 writeWithIndent("}"); 4429 } 4430 } break; 4431 } 4432 } 4433 4434 void StyledWriter::writeArrayValue(const Value& value) { 4435 unsigned size = value.size(); 4436 if (size == 0) 4437 pushValue("[]"); 4438 else { 4439 bool isArrayMultiLine = isMultineArray(value); 4440 if (isArrayMultiLine) { 4441 writeWithIndent("["); 4442 indent(); 4443 bool hasChildValue = !childValues_.empty(); 4444 unsigned index = 0; 4445 for (;;) { 4446 const Value& childValue = value[index]; 4447 writeCommentBeforeValue(childValue); 4448 if (hasChildValue) 4449 writeWithIndent(childValues_[index]); 4450 else { 4451 writeIndent(); 4452 writeValue(childValue); 4453 } 4454 if (++index == size) { 4455 writeCommentAfterValueOnSameLine(childValue); 4456 break; 4457 } 4458 document_ += ','; 4459 writeCommentAfterValueOnSameLine(childValue); 4460 } 4461 unindent(); 4462 writeWithIndent("]"); 4463 } else // output on a single line 4464 { 4465 assert(childValues_.size() == size); 4466 document_ += "[ "; 4467 for (unsigned index = 0; index < size; ++index) { 4468 if (index > 0) 4469 document_ += ", "; 4470 document_ += childValues_[index]; 4471 } 4472 document_ += " ]"; 4473 } 4474 } 4475 } 4476 4477 bool StyledWriter::isMultineArray(const Value& value) { 4478 int size = value.size(); 4479 bool isMultiLine = size * 3 >= rightMargin_; 4480 childValues_.clear(); 4481 for (int index = 0; index < size && !isMultiLine; ++index) { 4482 const Value& childValue = value[index]; 4483 isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4484 childValue.size() > 0); 4485 } 4486 if (!isMultiLine) // check if line length > max line length 4487 { 4488 childValues_.reserve(size); 4489 addChildValues_ = true; 4490 int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4491 for (int index = 0; index < size; ++index) { 4492 if (hasCommentForValue(value[index])) { 4493 isMultiLine = true; 4494 } 4495 writeValue(value[index]); 4496 lineLength += int(childValues_[index].length()); 4497 } 4498 addChildValues_ = false; 4499 isMultiLine = isMultiLine || lineLength >= rightMargin_; 4500 } 4501 return isMultiLine; 4502 } 4503 4504 void StyledWriter::pushValue(const std::string& value) { 4505 if (addChildValues_) 4506 childValues_.push_back(value); 4507 else 4508 document_ += value; 4509 } 4510 4511 void StyledWriter::writeIndent() { 4512 if (!document_.empty()) { 4513 char last = document_[document_.length() - 1]; 4514 if (last == ' ') // already indented 4515 return; 4516 if (last != '\n') // Comments may add new-line 4517 document_ += '\n'; 4518 } 4519 document_ += indentString_; 4520 } 4521 4522 void StyledWriter::writeWithIndent(const std::string& value) { 4523 writeIndent(); 4524 document_ += value; 4525 } 4526 4527 void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); } 4528 4529 void StyledWriter::unindent() { 4530 assert(int(indentString_.size()) >= indentSize_); 4531 indentString_.resize(indentString_.size() - indentSize_); 4532 } 4533 4534 void StyledWriter::writeCommentBeforeValue(const Value& root) { 4535 if (!root.hasComment(commentBefore)) 4536 return; 4537 4538 document_ += "\n"; 4539 writeIndent(); 4540 const std::string& comment = root.getComment(commentBefore); 4541 std::string::const_iterator iter = comment.begin(); 4542 while (iter != comment.end()) { 4543 document_ += *iter; 4544 if (*iter == '\n' && 4545 (iter != comment.end() && *(iter + 1) == '/')) 4546 writeIndent(); 4547 ++iter; 4548 } 4549 4550 // Comments are stripped of trailing newlines, so add one here 4551 document_ += "\n"; 4552 } 4553 4554 void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) { 4555 if (root.hasComment(commentAfterOnSameLine)) 4556 document_ += " " + root.getComment(commentAfterOnSameLine); 4557 4558 if (root.hasComment(commentAfter)) { 4559 document_ += "\n"; 4560 document_ += root.getComment(commentAfter); 4561 document_ += "\n"; 4562 } 4563 } 4564 4565 bool StyledWriter::hasCommentForValue(const Value& value) { 4566 return value.hasComment(commentBefore) || 4567 value.hasComment(commentAfterOnSameLine) || 4568 value.hasComment(commentAfter); 4569 } 4570 4571 // Class StyledStreamWriter 4572 // ////////////////////////////////////////////////////////////////// 4573 4574 StyledStreamWriter::StyledStreamWriter(std::string indentation) 4575 : document_(NULL), rightMargin_(74), indentation_(indentation), 4576 addChildValues_() {} 4577 4578 void StyledStreamWriter::write(std::ostream& out, const Value& root) { 4579 document_ = &out; 4580 addChildValues_ = false; 4581 indentString_ = ""; 4582 indented_ = true; 4583 writeCommentBeforeValue(root); 4584 if (!indented_) writeIndent(); 4585 indented_ = true; 4586 writeValue(root); 4587 writeCommentAfterValueOnSameLine(root); 4588 *document_ << "\n"; 4589 document_ = NULL; // Forget the stream, for safety. 4590 } 4591 4592 void StyledStreamWriter::writeValue(const Value& value) { 4593 switch (value.type()) { 4594 case nullValue: 4595 pushValue("null"); 4596 break; 4597 case intValue: 4598 pushValue(valueToString(value.asLargestInt())); 4599 break; 4600 case uintValue: 4601 pushValue(valueToString(value.asLargestUInt())); 4602 break; 4603 case realValue: 4604 pushValue(valueToString(value.asDouble())); 4605 break; 4606 case stringValue: 4607 { 4608 // Is NULL possible for value.string_? 4609 char const* str; 4610 char const* end; 4611 bool ok = value.getString(&str, &end); 4612 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4613 else pushValue(""); 4614 break; 4615 } 4616 case booleanValue: 4617 pushValue(valueToString(value.asBool())); 4618 break; 4619 case arrayValue: 4620 writeArrayValue(value); 4621 break; 4622 case objectValue: { 4623 Value::Members members(value.getMemberNames()); 4624 if (members.empty()) 4625 pushValue("{}"); 4626 else { 4627 writeWithIndent("{"); 4628 indent(); 4629 Value::Members::iterator it = members.begin(); 4630 for (;;) { 4631 const std::string& name = *it; 4632 const Value& childValue = value[name]; 4633 writeCommentBeforeValue(childValue); 4634 writeWithIndent(valueToQuotedString(name.c_str())); 4635 *document_ << " : "; 4636 writeValue(childValue); 4637 if (++it == members.end()) { 4638 writeCommentAfterValueOnSameLine(childValue); 4639 break; 4640 } 4641 *document_ << ","; 4642 writeCommentAfterValueOnSameLine(childValue); 4643 } 4644 unindent(); 4645 writeWithIndent("}"); 4646 } 4647 } break; 4648 } 4649 } 4650 4651 void StyledStreamWriter::writeArrayValue(const Value& value) { 4652 unsigned size = value.size(); 4653 if (size == 0) 4654 pushValue("[]"); 4655 else { 4656 bool isArrayMultiLine = isMultineArray(value); 4657 if (isArrayMultiLine) { 4658 writeWithIndent("["); 4659 indent(); 4660 bool hasChildValue = !childValues_.empty(); 4661 unsigned index = 0; 4662 for (;;) { 4663 const Value& childValue = value[index]; 4664 writeCommentBeforeValue(childValue); 4665 if (hasChildValue) 4666 writeWithIndent(childValues_[index]); 4667 else { 4668 if (!indented_) writeIndent(); 4669 indented_ = true; 4670 writeValue(childValue); 4671 indented_ = false; 4672 } 4673 if (++index == size) { 4674 writeCommentAfterValueOnSameLine(childValue); 4675 break; 4676 } 4677 *document_ << ","; 4678 writeCommentAfterValueOnSameLine(childValue); 4679 } 4680 unindent(); 4681 writeWithIndent("]"); 4682 } else // output on a single line 4683 { 4684 assert(childValues_.size() == size); 4685 *document_ << "[ "; 4686 for (unsigned index = 0; index < size; ++index) { 4687 if (index > 0) 4688 *document_ << ", "; 4689 *document_ << childValues_[index]; 4690 } 4691 *document_ << " ]"; 4692 } 4693 } 4694 } 4695 4696 bool StyledStreamWriter::isMultineArray(const Value& value) { 4697 int size = value.size(); 4698 bool isMultiLine = size * 3 >= rightMargin_; 4699 childValues_.clear(); 4700 for (int index = 0; index < size && !isMultiLine; ++index) { 4701 const Value& childValue = value[index]; 4702 isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4703 childValue.size() > 0); 4704 } 4705 if (!isMultiLine) // check if line length > max line length 4706 { 4707 childValues_.reserve(size); 4708 addChildValues_ = true; 4709 int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4710 for (int index = 0; index < size; ++index) { 4711 if (hasCommentForValue(value[index])) { 4712 isMultiLine = true; 4713 } 4714 writeValue(value[index]); 4715 lineLength += int(childValues_[index].length()); 4716 } 4717 addChildValues_ = false; 4718 isMultiLine = isMultiLine || lineLength >= rightMargin_; 4719 } 4720 return isMultiLine; 4721 } 4722 4723 void StyledStreamWriter::pushValue(const std::string& value) { 4724 if (addChildValues_) 4725 childValues_.push_back(value); 4726 else 4727 *document_ << value; 4728 } 4729 4730 void StyledStreamWriter::writeIndent() { 4731 // blep intended this to look at the so-far-written string 4732 // to determine whether we are already indented, but 4733 // with a stream we cannot do that. So we rely on some saved state. 4734 // The caller checks indented_. 4735 *document_ << '\n' << indentString_; 4736 } 4737 4738 void StyledStreamWriter::writeWithIndent(const std::string& value) { 4739 if (!indented_) writeIndent(); 4740 *document_ << value; 4741 indented_ = false; 4742 } 4743 4744 void StyledStreamWriter::indent() { indentString_ += indentation_; } 4745 4746 void StyledStreamWriter::unindent() { 4747 assert(indentString_.size() >= indentation_.size()); 4748 indentString_.resize(indentString_.size() - indentation_.size()); 4749 } 4750 4751 void StyledStreamWriter::writeCommentBeforeValue(const Value& root) { 4752 if (!root.hasComment(commentBefore)) 4753 return; 4754 4755 if (!indented_) writeIndent(); 4756 const std::string& comment = root.getComment(commentBefore); 4757 std::string::const_iterator iter = comment.begin(); 4758 while (iter != comment.end()) { 4759 *document_ << *iter; 4760 if (*iter == '\n' && 4761 (iter != comment.end() && *(iter + 1) == '/')) 4762 // writeIndent(); // would include newline 4763 *document_ << indentString_; 4764 ++iter; 4765 } 4766 indented_ = false; 4767 } 4768 4769 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) { 4770 if (root.hasComment(commentAfterOnSameLine)) 4771 *document_ << ' ' << root.getComment(commentAfterOnSameLine); 4772 4773 if (root.hasComment(commentAfter)) { 4774 writeIndent(); 4775 *document_ << root.getComment(commentAfter); 4776 } 4777 indented_ = false; 4778 } 4779 4780 bool StyledStreamWriter::hasCommentForValue(const Value& value) { 4781 return value.hasComment(commentBefore) || 4782 value.hasComment(commentAfterOnSameLine) || 4783 value.hasComment(commentAfter); 4784 } 4785 4786 ////////////////////////// 4787 // BuiltStyledStreamWriter 4788 4789 /// Scoped enums are not available until C++11. 4790 struct CommentStyle { 4791 /// Decide whether to write comments. 4792 enum Enum { 4793 None, ///< Drop all comments. 4794 Most, ///< Recover odd behavior of previous versions (not implemented yet). 4795 All ///< Keep all comments. 4796 }; 4797 }; 4798 4799 struct BuiltStyledStreamWriter : public StreamWriter 4800 { 4801 BuiltStyledStreamWriter( 4802 std::string const& indentation, 4803 CommentStyle::Enum cs, 4804 std::string const& colonSymbol, 4805 std::string const& nullSymbol, 4806 std::string const& endingLineFeedSymbol, 4807 bool useSpecialFloats, 4808 unsigned int precision); 4809 int write(Value const& root, std::ostream* sout) override; 4810 private: 4811 void writeValue(Value const& value); 4812 void writeArrayValue(Value const& value); 4813 bool isMultineArray(Value const& value); 4814 void pushValue(std::string const& value); 4815 void writeIndent(); 4816 void writeWithIndent(std::string const& value); 4817 void indent(); 4818 void unindent(); 4819 void writeCommentBeforeValue(Value const& root); 4820 void writeCommentAfterValueOnSameLine(Value const& root); 4821 static bool hasCommentForValue(const Value& value); 4822 4823 typedef std::vector<std::string> ChildValues; 4824 4825 ChildValues childValues_; 4826 std::string indentString_; 4827 int rightMargin_; 4828 std::string indentation_; 4829 CommentStyle::Enum cs_; 4830 std::string colonSymbol_; 4831 std::string nullSymbol_; 4832 std::string endingLineFeedSymbol_; 4833 bool addChildValues_ : 1; 4834 bool indented_ : 1; 4835 bool useSpecialFloats_ : 1; 4836 unsigned int precision_; 4837 }; 4838 BuiltStyledStreamWriter::BuiltStyledStreamWriter( 4839 std::string const& indentation, 4840 CommentStyle::Enum cs, 4841 std::string const& colonSymbol, 4842 std::string const& nullSymbol, 4843 std::string const& endingLineFeedSymbol, 4844 bool useSpecialFloats, 4845 unsigned int precision) 4846 : rightMargin_(74) 4847 , indentation_(indentation) 4848 , cs_(cs) 4849 , colonSymbol_(colonSymbol) 4850 , nullSymbol_(nullSymbol) 4851 , endingLineFeedSymbol_(endingLineFeedSymbol) 4852 , addChildValues_(false) 4853 , indented_(false) 4854 , useSpecialFloats_(useSpecialFloats) 4855 , precision_(precision) 4856 { 4857 } 4858 int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout) 4859 { 4860 sout_ = sout; 4861 addChildValues_ = false; 4862 indented_ = true; 4863 indentString_ = ""; 4864 writeCommentBeforeValue(root); 4865 if (!indented_) writeIndent(); 4866 indented_ = true; 4867 writeValue(root); 4868 writeCommentAfterValueOnSameLine(root); 4869 *sout_ << endingLineFeedSymbol_; 4870 sout_ = NULL; 4871 return 0; 4872 } 4873 void BuiltStyledStreamWriter::writeValue(Value const& value) { 4874 switch (value.type()) { 4875 case nullValue: 4876 pushValue(nullSymbol_); 4877 break; 4878 case intValue: 4879 pushValue(valueToString(value.asLargestInt())); 4880 break; 4881 case uintValue: 4882 pushValue(valueToString(value.asLargestUInt())); 4883 break; 4884 case realValue: 4885 pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_)); 4886 break; 4887 case stringValue: 4888 { 4889 // Is NULL is possible for value.string_? 4890 char const* str; 4891 char const* end; 4892 bool ok = value.getString(&str, &end); 4893 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str))); 4894 else pushValue(""); 4895 break; 4896 } 4897 case booleanValue: 4898 pushValue(valueToString(value.asBool())); 4899 break; 4900 case arrayValue: 4901 writeArrayValue(value); 4902 break; 4903 case objectValue: { 4904 Value::Members members(value.getMemberNames()); 4905 if (members.empty()) 4906 pushValue("{}"); 4907 else { 4908 writeWithIndent("{"); 4909 indent(); 4910 Value::Members::iterator it = members.begin(); 4911 for (;;) { 4912 std::string const& name = *it; 4913 Value const& childValue = value[name]; 4914 writeCommentBeforeValue(childValue); 4915 writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()))); 4916 *sout_ << colonSymbol_; 4917 writeValue(childValue); 4918 if (++it == members.end()) { 4919 writeCommentAfterValueOnSameLine(childValue); 4920 break; 4921 } 4922 *sout_ << ","; 4923 writeCommentAfterValueOnSameLine(childValue); 4924 } 4925 unindent(); 4926 writeWithIndent("}"); 4927 } 4928 } break; 4929 } 4930 } 4931 4932 void BuiltStyledStreamWriter::writeArrayValue(Value const& value) { 4933 unsigned size = value.size(); 4934 if (size == 0) 4935 pushValue("[]"); 4936 else { 4937 bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); 4938 if (isMultiLine) { 4939 writeWithIndent("["); 4940 indent(); 4941 bool hasChildValue = !childValues_.empty(); 4942 unsigned index = 0; 4943 for (;;) { 4944 Value const& childValue = value[index]; 4945 writeCommentBeforeValue(childValue); 4946 if (hasChildValue) 4947 writeWithIndent(childValues_[index]); 4948 else { 4949 if (!indented_) writeIndent(); 4950 indented_ = true; 4951 writeValue(childValue); 4952 indented_ = false; 4953 } 4954 if (++index == size) { 4955 writeCommentAfterValueOnSameLine(childValue); 4956 break; 4957 } 4958 *sout_ << ","; 4959 writeCommentAfterValueOnSameLine(childValue); 4960 } 4961 unindent(); 4962 writeWithIndent("]"); 4963 } else // output on a single line 4964 { 4965 assert(childValues_.size() == size); 4966 *sout_ << "["; 4967 if (!indentation_.empty()) *sout_ << " "; 4968 for (unsigned index = 0; index < size; ++index) { 4969 if (index > 0) 4970 *sout_ << ", "; 4971 *sout_ << childValues_[index]; 4972 } 4973 if (!indentation_.empty()) *sout_ << " "; 4974 *sout_ << "]"; 4975 } 4976 } 4977 } 4978 4979 bool BuiltStyledStreamWriter::isMultineArray(Value const& value) { 4980 int size = value.size(); 4981 bool isMultiLine = size * 3 >= rightMargin_; 4982 childValues_.clear(); 4983 for (int index = 0; index < size && !isMultiLine; ++index) { 4984 Value const& childValue = value[index]; 4985 isMultiLine = ((childValue.isArray() || childValue.isObject()) && 4986 childValue.size() > 0); 4987 } 4988 if (!isMultiLine) // check if line length > max line length 4989 { 4990 childValues_.reserve(size); 4991 addChildValues_ = true; 4992 int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]' 4993 for (int index = 0; index < size; ++index) { 4994 if (hasCommentForValue(value[index])) { 4995 isMultiLine = true; 4996 } 4997 writeValue(value[index]); 4998 lineLength += int(childValues_[index].length()); 4999 } 5000 addChildValues_ = false; 5001 isMultiLine = isMultiLine || lineLength >= rightMargin_; 5002 } 5003 return isMultiLine; 5004 } 5005 5006 void BuiltStyledStreamWriter::pushValue(std::string const& value) { 5007 if (addChildValues_) 5008 childValues_.push_back(value); 5009 else 5010 *sout_ << value; 5011 } 5012 5013 void BuiltStyledStreamWriter::writeIndent() { 5014 // blep intended this to look at the so-far-written string 5015 // to determine whether we are already indented, but 5016 // with a stream we cannot do that. So we rely on some saved state. 5017 // The caller checks indented_. 5018 5019 if (!indentation_.empty()) { 5020 // In this case, drop newlines too. 5021 *sout_ << '\n' << indentString_; 5022 } 5023 } 5024 5025 void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) { 5026 if (!indented_) writeIndent(); 5027 *sout_ << value; 5028 indented_ = false; 5029 } 5030 5031 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; } 5032 5033 void BuiltStyledStreamWriter::unindent() { 5034 assert(indentString_.size() >= indentation_.size()); 5035 indentString_.resize(indentString_.size() - indentation_.size()); 5036 } 5037 5038 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) { 5039 if (cs_ == CommentStyle::None) return; 5040 if (!root.hasComment(commentBefore)) 5041 return; 5042 5043 if (!indented_) writeIndent(); 5044 const std::string& comment = root.getComment(commentBefore); 5045 std::string::const_iterator iter = comment.begin(); 5046 while (iter != comment.end()) { 5047 *sout_ << *iter; 5048 if (*iter == '\n' && 5049 (iter != comment.end() && *(iter + 1) == '/')) 5050 // writeIndent(); // would write extra newline 5051 *sout_ << indentString_; 5052 ++iter; 5053 } 5054 indented_ = false; 5055 } 5056 5057 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) { 5058 if (cs_ == CommentStyle::None) return; 5059 if (root.hasComment(commentAfterOnSameLine)) 5060 *sout_ << " " + root.getComment(commentAfterOnSameLine); 5061 5062 if (root.hasComment(commentAfter)) { 5063 writeIndent(); 5064 *sout_ << root.getComment(commentAfter); 5065 } 5066 } 5067 5068 // static 5069 bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) { 5070 return value.hasComment(commentBefore) || 5071 value.hasComment(commentAfterOnSameLine) || 5072 value.hasComment(commentAfter); 5073 } 5074 5075 /////////////// 5076 // StreamWriter 5077 5078 StreamWriter::StreamWriter() 5079 : sout_(NULL) 5080 { 5081 } 5082 StreamWriter::~StreamWriter() 5083 { 5084 } 5085 StreamWriter::Factory::~Factory() 5086 {} 5087 StreamWriterBuilder::StreamWriterBuilder() 5088 { 5089 setDefaults(&settings_); 5090 } 5091 StreamWriterBuilder::~StreamWriterBuilder() 5092 {} 5093 StreamWriter* StreamWriterBuilder::newStreamWriter() const 5094 { 5095 std::string indentation = settings_["indentation"].asString(); 5096 std::string cs_str = settings_["commentStyle"].asString(); 5097 bool eyc = settings_["enableYAMLCompatibility"].asBool(); 5098 bool dnp = settings_["dropNullPlaceholders"].asBool(); 5099 bool usf = settings_["useSpecialFloats"].asBool(); 5100 unsigned int pre = settings_["precision"].asUInt(); 5101 CommentStyle::Enum cs = CommentStyle::All; 5102 if (cs_str == "All") { 5103 cs = CommentStyle::All; 5104 } else if (cs_str == "None") { 5105 cs = CommentStyle::None; 5106 } else { 5107 throwRuntimeError("commentStyle must be 'All' or 'None'"); 5108 } 5109 std::string colonSymbol = " : "; 5110 if (eyc) { 5111 colonSymbol = ": "; 5112 } else if (indentation.empty()) { 5113 colonSymbol = ":"; 5114 } 5115 std::string nullSymbol = "null"; 5116 if (dnp) { 5117 nullSymbol = ""; 5118 } 5119 if (pre > 17) pre = 17; 5120 std::string endingLineFeedSymbol = ""; 5121 return new BuiltStyledStreamWriter( 5122 indentation, cs, 5123 colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre); 5124 } 5125 static void getValidWriterKeys(std::set<std::string>* valid_keys) 5126 { 5127 valid_keys->clear(); 5128 valid_keys->insert("indentation"); 5129 valid_keys->insert("commentStyle"); 5130 valid_keys->insert("enableYAMLCompatibility"); 5131 valid_keys->insert("dropNullPlaceholders"); 5132 valid_keys->insert("useSpecialFloats"); 5133 valid_keys->insert("precision"); 5134 } 5135 bool StreamWriterBuilder::validate(Json::Value* invalid) const 5136 { 5137 Json::Value my_invalid; 5138 if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL 5139 Json::Value& inv = *invalid; 5140 std::set<std::string> valid_keys; 5141 getValidWriterKeys(&valid_keys); 5142 Value::Members keys = settings_.getMemberNames(); 5143 size_t n = keys.size(); 5144 for (size_t i = 0; i < n; ++i) { 5145 std::string const& key = keys[i]; 5146 if (valid_keys.find(key) == valid_keys.end()) { 5147 inv[key] = settings_[key]; 5148 } 5149 } 5150 return 0u == inv.size(); 5151 } 5152 Value& StreamWriterBuilder::operator[](std::string key) 5153 { 5154 return settings_[key]; 5155 } 5156 // static 5157 void StreamWriterBuilder::setDefaults(Json::Value* settings) 5158 { 5159 //! [StreamWriterBuilderDefaults] 5160 (*settings)["commentStyle"] = "All"; 5161 (*settings)["indentation"] = "\t"; 5162 (*settings)["enableYAMLCompatibility"] = false; 5163 (*settings)["dropNullPlaceholders"] = false; 5164 (*settings)["useSpecialFloats"] = false; 5165 (*settings)["precision"] = 17; 5166 //! [StreamWriterBuilderDefaults] 5167 } 5168 5169 std::string writeString(StreamWriter::Factory const& builder, Value const& root) { 5170 std::ostringstream sout; 5171 StreamWriterPtr const writer(builder.newStreamWriter()); 5172 writer->write(root, &sout); 5173 return sout.str(); 5174 } 5175 5176 std::ostream& operator<<(std::ostream& sout, Value const& root) { 5177 StreamWriterBuilder builder; 5178 StreamWriterPtr const writer(builder.newStreamWriter()); 5179 writer->write(root, &sout); 5180 return sout; 5181 } 5182 5183 } // namespace Json 5184 5185 // ////////////////////////////////////////////////////////////////////// 5186 // End of content of file: src/lib_json/json_writer.cpp 5187 // ////////////////////////////////////////////////////////////////////// 5188 5189 5190 5191 5192 5193