File indexing completed on 2025-01-18 09:15:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076 #include "json/json.h"
0077
0078 #ifndef JSON_IS_AMALGAMATION
0079 #error "Compile with -I PATH_TO_JSON_DIRECTORY"
0080 #endif
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
0093 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
0094
0095
0096
0097 #ifdef NO_LOCALE_SUPPORT
0098 #define JSONCPP_NO_LOCALE_SUPPORT
0099 #endif
0100
0101 #ifndef JSONCPP_NO_LOCALE_SUPPORT
0102 #include <clocale>
0103 #endif
0104
0105
0106
0107
0108
0109
0110
0111 namespace Json {
0112 static char getDecimalPoint() {
0113 #ifdef JSONCPP_NO_LOCALE_SUPPORT
0114 return '\0';
0115 #else
0116 struct lconv* lc = localeconv();
0117 return lc ? *(lc->decimal_point) : '\0';
0118 #endif
0119 }
0120
0121
0122 static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
0123 JSONCPP_STRING result;
0124
0125
0126
0127 if (cp <= 0x7f) {
0128 result.resize(1);
0129 result[0] = static_cast<char>(cp);
0130 } else if (cp <= 0x7FF) {
0131 result.resize(2);
0132 result[1] = static_cast<char>(0x80 | (0x3f & cp));
0133 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
0134 } else if (cp <= 0xFFFF) {
0135 result.resize(3);
0136 result[2] = static_cast<char>(0x80 | (0x3f & cp));
0137 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
0138 result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
0139 } else if (cp <= 0x10FFFF) {
0140 result.resize(4);
0141 result[3] = static_cast<char>(0x80 | (0x3f & cp));
0142 result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
0143 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
0144 result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
0145 }
0146
0147 return result;
0148 }
0149
0150 enum {
0151
0152
0153 uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
0154 };
0155
0156
0157 typedef char UIntToStringBuffer[uintToStringBufferSize];
0158
0159
0160
0161
0162
0163
0164 static inline void uintToString(LargestUInt value, char*& current) {
0165 *--current = 0;
0166 do {
0167 *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
0168 value /= 10;
0169 } while (value != 0);
0170 }
0171
0172
0173
0174
0175
0176
0177 static inline void fixNumericLocale(char* begin, char* end) {
0178 while (begin < end) {
0179 if (*begin == ',') {
0180 *begin = '.';
0181 }
0182 ++begin;
0183 }
0184 }
0185
0186 static inline void fixNumericLocaleInput(char* begin, char* end) {
0187 char decimalPoint = getDecimalPoint();
0188 if (decimalPoint != '\0' && decimalPoint != '.') {
0189 while (begin < end) {
0190 if (*begin == '.') {
0191 *begin = decimalPoint;
0192 }
0193 ++begin;
0194 }
0195 }
0196 }
0197
0198
0199
0200
0201 static inline void fixZerosInTheEnd(char* begin, char* end) {
0202 end--;
0203 while ((begin < end) && (*end == '0')) {
0204
0205 if (*(end - 1) != '.') {
0206 *end = '\0';
0207 }
0208 end--;
0209 }
0210 }
0211
0212 }
0213
0214 #endif
0215
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235 #if !defined(JSON_IS_AMALGAMATION)
0236 #include <json/assertions.h>
0237 #include <json/reader.h>
0238 #include <json/value.h>
0239 #include "json_tool.h"
0240 #endif
0241 #include <utility>
0242 #include <cstdio>
0243 #include <cassert>
0244 #include <cstring>
0245 #include <istream>
0246 #include <sstream>
0247 #include <memory>
0248 #include <set>
0249 #include <limits>
0250
0251 #if defined(_MSC_VER)
0252 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500
0253 #define snprintf sprintf_s
0254 #elif _MSC_VER >= 1900
0255 #define snprintf std::snprintf
0256 #else
0257 #define snprintf _snprintf
0258 #endif
0259 #elif defined(__ANDROID__) || defined(__QNXNTO__)
0260 #define snprintf snprintf
0261 #elif __cplusplus >= 201103L
0262 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
0263 #define snprintf std::snprintf
0264 #endif
0265 #endif
0266
0267 #if defined(__QNXNTO__)
0268 #define sscanf std::sscanf
0269 #endif
0270
0271 #if defined(_MSC_VER) && _MSC_VER >= 1400
0272
0273 #pragma warning(disable : 4996)
0274 #endif
0275
0276
0277 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
0278 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000
0279 #endif
0280
0281 static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT;
0282
0283 namespace Json {
0284
0285 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
0286 typedef std::unique_ptr<CharReader> CharReaderPtr;
0287 #else
0288 typedef std::auto_ptr<CharReader> CharReaderPtr;
0289 #endif
0290
0291
0292
0293
0294 Features::Features()
0295 : allowComments_(true), strictRoot_(false),
0296 allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
0297
0298 Features Features::all() { return Features(); }
0299
0300 Features Features::strictMode() {
0301 Features features;
0302 features.allowComments_ = false;
0303 features.strictRoot_ = true;
0304 features.allowDroppedNullPlaceholders_ = false;
0305 features.allowNumericKeys_ = false;
0306 return features;
0307 }
0308
0309
0310
0311
0312 bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
0313 for (; begin < end; ++begin)
0314 if (*begin == '\n' || *begin == '\r')
0315 return true;
0316 return false;
0317 }
0318
0319
0320
0321
0322 Reader::Reader()
0323 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
0324 lastValue_(), commentsBefore_(), features_(Features::all()),
0325 collectComments_() {}
0326
0327 Reader::Reader(const Features& features)
0328 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
0329 lastValue_(), commentsBefore_(), features_(features), collectComments_() {
0330 }
0331
0332 bool
0333 Reader::parse(const std::string& document, Value& root, bool collectComments) {
0334 document_.assign(document.begin(), document.end());
0335 const char* begin = document_.c_str();
0336 const char* end = begin + document_.length();
0337 return parse(begin, end, root, collectComments);
0338 }
0339
0340 bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
0341
0342
0343
0344
0345
0346
0347
0348 JSONCPP_STRING doc;
0349 std::getline(sin, doc, (char)EOF);
0350 return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
0351 }
0352
0353 bool Reader::parse(const char* beginDoc,
0354 const char* endDoc,
0355 Value& root,
0356 bool collectComments) {
0357 if (!features_.allowComments_) {
0358 collectComments = false;
0359 }
0360
0361 begin_ = beginDoc;
0362 end_ = endDoc;
0363 collectComments_ = collectComments;
0364 current_ = begin_;
0365 lastValueEnd_ = 0;
0366 lastValue_ = 0;
0367 commentsBefore_.clear();
0368 errors_.clear();
0369 while (!nodes_.empty())
0370 nodes_.pop();
0371 nodes_.push(&root);
0372
0373 bool successful = readValue();
0374 Token token;
0375 skipCommentTokens(token);
0376 if (collectComments_ && !commentsBefore_.empty())
0377 root.setComment(commentsBefore_, commentAfter);
0378 if (features_.strictRoot_) {
0379 if (!root.isArray() && !root.isObject()) {
0380
0381
0382 token.type_ = tokenError;
0383 token.start_ = beginDoc;
0384 token.end_ = endDoc;
0385 addError(
0386 "A valid JSON document must be either an array or an object value.",
0387 token);
0388 return false;
0389 }
0390 }
0391 return successful;
0392 }
0393
0394 bool Reader::readValue() {
0395
0396
0397
0398 if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
0399
0400 Token token;
0401 skipCommentTokens(token);
0402 bool successful = true;
0403
0404 if (collectComments_ && !commentsBefore_.empty()) {
0405 currentValue().setComment(commentsBefore_, commentBefore);
0406 commentsBefore_.clear();
0407 }
0408
0409 switch (token.type_) {
0410 case tokenObjectBegin:
0411 successful = readObject(token);
0412 currentValue().setOffsetLimit(current_ - begin_);
0413 break;
0414 case tokenArrayBegin:
0415 successful = readArray(token);
0416 currentValue().setOffsetLimit(current_ - begin_);
0417 break;
0418 case tokenNumber:
0419 successful = decodeNumber(token);
0420 break;
0421 case tokenString:
0422 successful = decodeString(token);
0423 break;
0424 case tokenTrue:
0425 {
0426 Value v(true);
0427 currentValue().swapPayload(v);
0428 currentValue().setOffsetStart(token.start_ - begin_);
0429 currentValue().setOffsetLimit(token.end_ - begin_);
0430 }
0431 break;
0432 case tokenFalse:
0433 {
0434 Value v(false);
0435 currentValue().swapPayload(v);
0436 currentValue().setOffsetStart(token.start_ - begin_);
0437 currentValue().setOffsetLimit(token.end_ - begin_);
0438 }
0439 break;
0440 case tokenNull:
0441 {
0442 Value v;
0443 currentValue().swapPayload(v);
0444 currentValue().setOffsetStart(token.start_ - begin_);
0445 currentValue().setOffsetLimit(token.end_ - begin_);
0446 }
0447 break;
0448 case tokenArraySeparator:
0449 case tokenObjectEnd:
0450 case tokenArrayEnd:
0451 if (features_.allowDroppedNullPlaceholders_) {
0452
0453
0454 current_--;
0455 Value v;
0456 currentValue().swapPayload(v);
0457 currentValue().setOffsetStart(current_ - begin_ - 1);
0458 currentValue().setOffsetLimit(current_ - begin_);
0459 break;
0460 }
0461 default:
0462 currentValue().setOffsetStart(token.start_ - begin_);
0463 currentValue().setOffsetLimit(token.end_ - begin_);
0464 return addError("Syntax error: value, object or array expected.", token);
0465 }
0466
0467 if (collectComments_) {
0468 lastValueEnd_ = current_;
0469 lastValue_ = ¤tValue();
0470 }
0471
0472 return successful;
0473 }
0474
0475 void Reader::skipCommentTokens(Token& token) {
0476 if (features_.allowComments_) {
0477 do {
0478 readToken(token);
0479 } while (token.type_ == tokenComment);
0480 } else {
0481 readToken(token);
0482 }
0483 }
0484
0485 bool Reader::readToken(Token& token) {
0486 skipSpaces();
0487 token.start_ = current_;
0488 Char c = getNextChar();
0489 bool ok = true;
0490 switch (c) {
0491 case '{':
0492 token.type_ = tokenObjectBegin;
0493 break;
0494 case '}':
0495 token.type_ = tokenObjectEnd;
0496 break;
0497 case '[':
0498 token.type_ = tokenArrayBegin;
0499 break;
0500 case ']':
0501 token.type_ = tokenArrayEnd;
0502 break;
0503 case '"':
0504 token.type_ = tokenString;
0505 ok = readString();
0506 break;
0507 case '/':
0508 token.type_ = tokenComment;
0509 ok = readComment();
0510 break;
0511 case '0':
0512 case '1':
0513 case '2':
0514 case '3':
0515 case '4':
0516 case '5':
0517 case '6':
0518 case '7':
0519 case '8':
0520 case '9':
0521 case '-':
0522 token.type_ = tokenNumber;
0523 readNumber();
0524 break;
0525 case 't':
0526 token.type_ = tokenTrue;
0527 ok = match("rue", 3);
0528 break;
0529 case 'f':
0530 token.type_ = tokenFalse;
0531 ok = match("alse", 4);
0532 break;
0533 case 'n':
0534 token.type_ = tokenNull;
0535 ok = match("ull", 3);
0536 break;
0537 case ',':
0538 token.type_ = tokenArraySeparator;
0539 break;
0540 case ':':
0541 token.type_ = tokenMemberSeparator;
0542 break;
0543 case 0:
0544 token.type_ = tokenEndOfStream;
0545 break;
0546 default:
0547 ok = false;
0548 break;
0549 }
0550 if (!ok)
0551 token.type_ = tokenError;
0552 token.end_ = current_;
0553 return true;
0554 }
0555
0556 void Reader::skipSpaces() {
0557 while (current_ != end_) {
0558 Char c = *current_;
0559 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
0560 ++current_;
0561 else
0562 break;
0563 }
0564 }
0565
0566 bool Reader::match(Location pattern, int patternLength) {
0567 if (end_ - current_ < patternLength)
0568 return false;
0569 int index = patternLength;
0570 while (index--)
0571 if (current_[index] != pattern[index])
0572 return false;
0573 current_ += patternLength;
0574 return true;
0575 }
0576
0577 bool Reader::readComment() {
0578 Location commentBegin = current_ - 1;
0579 Char c = getNextChar();
0580 bool successful = false;
0581 if (c == '*')
0582 successful = readCStyleComment();
0583 else if (c == '/')
0584 successful = readCppStyleComment();
0585 if (!successful)
0586 return false;
0587
0588 if (collectComments_) {
0589 CommentPlacement placement = commentBefore;
0590 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
0591 if (c != '*' || !containsNewLine(commentBegin, current_))
0592 placement = commentAfterOnSameLine;
0593 }
0594
0595 addComment(commentBegin, current_, placement);
0596 }
0597 return true;
0598 }
0599
0600 JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
0601 JSONCPP_STRING normalized;
0602 normalized.reserve(static_cast<size_t>(end - begin));
0603 Reader::Location current = begin;
0604 while (current != end) {
0605 char c = *current++;
0606 if (c == '\r') {
0607 if (current != end && *current == '\n')
0608
0609 ++current;
0610
0611 normalized += '\n';
0612 } else {
0613 normalized += c;
0614 }
0615 }
0616 return normalized;
0617 }
0618
0619 void
0620 Reader::addComment(Location begin, Location end, CommentPlacement placement) {
0621 assert(collectComments_);
0622 const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
0623 if (placement == commentAfterOnSameLine) {
0624 assert(lastValue_ != 0);
0625 lastValue_->setComment(normalized, placement);
0626 } else {
0627 commentsBefore_ += normalized;
0628 }
0629 }
0630
0631 bool Reader::readCStyleComment() {
0632 while ((current_ + 1) < end_) {
0633 Char c = getNextChar();
0634 if (c == '*' && *current_ == '/')
0635 break;
0636 }
0637 return getNextChar() == '/';
0638 }
0639
0640 bool Reader::readCppStyleComment() {
0641 while (current_ != end_) {
0642 Char c = getNextChar();
0643 if (c == '\n')
0644 break;
0645 if (c == '\r') {
0646
0647 if (current_ != end_ && *current_ == '\n')
0648 getNextChar();
0649
0650 break;
0651 }
0652 }
0653 return true;
0654 }
0655
0656 void Reader::readNumber() {
0657 const char *p = current_;
0658 char c = '0';
0659
0660 while (c >= '0' && c <= '9')
0661 c = (current_ = p) < end_ ? *p++ : '\0';
0662
0663 if (c == '.') {
0664 c = (current_ = p) < end_ ? *p++ : '\0';
0665 while (c >= '0' && c <= '9')
0666 c = (current_ = p) < end_ ? *p++ : '\0';
0667 }
0668
0669 if (c == 'e' || c == 'E') {
0670 c = (current_ = p) < end_ ? *p++ : '\0';
0671 if (c == '+' || c == '-')
0672 c = (current_ = p) < end_ ? *p++ : '\0';
0673 while (c >= '0' && c <= '9')
0674 c = (current_ = p) < end_ ? *p++ : '\0';
0675 }
0676 }
0677
0678 bool Reader::readString() {
0679 Char c = '\0';
0680 while (current_ != end_) {
0681 c = getNextChar();
0682 if (c == '\\')
0683 getNextChar();
0684 else if (c == '"')
0685 break;
0686 }
0687 return c == '"';
0688 }
0689
0690 bool Reader::readObject(Token& tokenStart) {
0691 Token tokenName;
0692 JSONCPP_STRING name;
0693 Value init(objectValue);
0694 currentValue().swapPayload(init);
0695 currentValue().setOffsetStart(tokenStart.start_ - begin_);
0696 while (readToken(tokenName)) {
0697 bool initialTokenOk = true;
0698 while (tokenName.type_ == tokenComment && initialTokenOk)
0699 initialTokenOk = readToken(tokenName);
0700 if (!initialTokenOk)
0701 break;
0702 if (tokenName.type_ == tokenObjectEnd && name.empty())
0703 return true;
0704 name.clear();
0705 if (tokenName.type_ == tokenString) {
0706 if (!decodeString(tokenName, name))
0707 return recoverFromError(tokenObjectEnd);
0708 } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
0709 Value numberName;
0710 if (!decodeNumber(tokenName, numberName))
0711 return recoverFromError(tokenObjectEnd);
0712 name = JSONCPP_STRING(numberName.asCString());
0713 } else {
0714 break;
0715 }
0716
0717 Token colon;
0718 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
0719 return addErrorAndRecover(
0720 "Missing ':' after object member name", colon, tokenObjectEnd);
0721 }
0722 Value& value = currentValue()[name];
0723 nodes_.push(&value);
0724 bool ok = readValue();
0725 nodes_.pop();
0726 if (!ok)
0727 return recoverFromError(tokenObjectEnd);
0728
0729 Token comma;
0730 if (!readToken(comma) ||
0731 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
0732 comma.type_ != tokenComment)) {
0733 return addErrorAndRecover(
0734 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
0735 }
0736 bool finalizeTokenOk = true;
0737 while (comma.type_ == tokenComment && finalizeTokenOk)
0738 finalizeTokenOk = readToken(comma);
0739 if (comma.type_ == tokenObjectEnd)
0740 return true;
0741 }
0742 return addErrorAndRecover(
0743 "Missing '}' or object member name", tokenName, tokenObjectEnd);
0744 }
0745
0746 bool Reader::readArray(Token& tokenStart) {
0747 Value init(arrayValue);
0748 currentValue().swapPayload(init);
0749 currentValue().setOffsetStart(tokenStart.start_ - begin_);
0750 skipSpaces();
0751 if (current_ != end_ && *current_ == ']')
0752 {
0753 Token endArray;
0754 readToken(endArray);
0755 return true;
0756 }
0757 int index = 0;
0758 for (;;) {
0759 Value& value = currentValue()[index++];
0760 nodes_.push(&value);
0761 bool ok = readValue();
0762 nodes_.pop();
0763 if (!ok)
0764 return recoverFromError(tokenArrayEnd);
0765
0766 Token token;
0767
0768 ok = readToken(token);
0769 while (token.type_ == tokenComment && ok) {
0770 ok = readToken(token);
0771 }
0772 bool badTokenType =
0773 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
0774 if (!ok || badTokenType) {
0775 return addErrorAndRecover(
0776 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
0777 }
0778 if (token.type_ == tokenArrayEnd)
0779 break;
0780 }
0781 return true;
0782 }
0783
0784 bool Reader::decodeNumber(Token& token) {
0785 Value decoded;
0786 if (!decodeNumber(token, decoded))
0787 return false;
0788 currentValue().swapPayload(decoded);
0789 currentValue().setOffsetStart(token.start_ - begin_);
0790 currentValue().setOffsetLimit(token.end_ - begin_);
0791 return true;
0792 }
0793
0794 bool Reader::decodeNumber(Token& token, Value& decoded) {
0795
0796
0797
0798 Location current = token.start_;
0799 bool isNegative = *current == '-';
0800 if (isNegative)
0801 ++current;
0802
0803 Value::LargestUInt maxIntegerValue =
0804 isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
0805 : Value::maxLargestUInt;
0806 Value::LargestUInt threshold = maxIntegerValue / 10;
0807 Value::LargestUInt value = 0;
0808 while (current < token.end_) {
0809 Char c = *current++;
0810 if (c < '0' || c > '9')
0811 return decodeDouble(token, decoded);
0812 Value::UInt digit(static_cast<Value::UInt>(c - '0'));
0813 if (value >= threshold) {
0814
0815
0816
0817
0818 if (value > threshold || current != token.end_ ||
0819 digit > maxIntegerValue % 10) {
0820 return decodeDouble(token, decoded);
0821 }
0822 }
0823 value = value * 10 + digit;
0824 }
0825 if (isNegative && value == maxIntegerValue)
0826 decoded = Value::minLargestInt;
0827 else if (isNegative)
0828 decoded = -Value::LargestInt(value);
0829 else if (value <= Value::LargestUInt(Value::maxInt))
0830 decoded = Value::LargestInt(value);
0831 else
0832 decoded = value;
0833 return true;
0834 }
0835
0836 bool Reader::decodeDouble(Token& token) {
0837 Value decoded;
0838 if (!decodeDouble(token, decoded))
0839 return false;
0840 currentValue().swapPayload(decoded);
0841 currentValue().setOffsetStart(token.start_ - begin_);
0842 currentValue().setOffsetLimit(token.end_ - begin_);
0843 return true;
0844 }
0845
0846 bool Reader::decodeDouble(Token& token, Value& decoded) {
0847 double value = 0;
0848 JSONCPP_STRING buffer(token.start_, token.end_);
0849 JSONCPP_ISTRINGSTREAM is(buffer);
0850 if (!(is >> value))
0851 return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
0852 "' is not a number.",
0853 token);
0854 decoded = value;
0855 return true;
0856 }
0857
0858 bool Reader::decodeString(Token& token) {
0859 JSONCPP_STRING decoded_string;
0860 if (!decodeString(token, decoded_string))
0861 return false;
0862 Value decoded(decoded_string);
0863 currentValue().swapPayload(decoded);
0864 currentValue().setOffsetStart(token.start_ - begin_);
0865 currentValue().setOffsetLimit(token.end_ - begin_);
0866 return true;
0867 }
0868
0869 bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
0870 decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
0871 Location current = token.start_ + 1;
0872 Location end = token.end_ - 1;
0873 while (current != end) {
0874 Char c = *current++;
0875 if (c == '"')
0876 break;
0877 else if (c == '\\') {
0878 if (current == end)
0879 return addError("Empty escape sequence in string", token, current);
0880 Char escape = *current++;
0881 switch (escape) {
0882 case '"':
0883 decoded += '"';
0884 break;
0885 case '/':
0886 decoded += '/';
0887 break;
0888 case '\\':
0889 decoded += '\\';
0890 break;
0891 case 'b':
0892 decoded += '\b';
0893 break;
0894 case 'f':
0895 decoded += '\f';
0896 break;
0897 case 'n':
0898 decoded += '\n';
0899 break;
0900 case 'r':
0901 decoded += '\r';
0902 break;
0903 case 't':
0904 decoded += '\t';
0905 break;
0906 case 'u': {
0907 unsigned int unicode;
0908 if (!decodeUnicodeCodePoint(token, current, end, unicode))
0909 return false;
0910 decoded += codePointToUTF8(unicode);
0911 } break;
0912 default:
0913 return addError("Bad escape sequence in string", token, current);
0914 }
0915 } else {
0916 decoded += c;
0917 }
0918 }
0919 return true;
0920 }
0921
0922 bool Reader::decodeUnicodeCodePoint(Token& token,
0923 Location& current,
0924 Location end,
0925 unsigned int& unicode) {
0926
0927 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
0928 return false;
0929 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
0930
0931 if (end - current < 6)
0932 return addError(
0933 "additional six characters expected to parse unicode surrogate pair.",
0934 token,
0935 current);
0936 unsigned int surrogatePair;
0937 if (*(current++) == '\\' && *(current++) == 'u') {
0938 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
0939 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
0940 } else
0941 return false;
0942 } else
0943 return addError("expecting another \\u token to begin the second half of "
0944 "a unicode surrogate pair",
0945 token,
0946 current);
0947 }
0948 return true;
0949 }
0950
0951 bool Reader::decodeUnicodeEscapeSequence(Token& token,
0952 Location& current,
0953 Location end,
0954 unsigned int& ret_unicode) {
0955 if (end - current < 4)
0956 return addError(
0957 "Bad unicode escape sequence in string: four digits expected.",
0958 token,
0959 current);
0960 int unicode = 0;
0961 for (int index = 0; index < 4; ++index) {
0962 Char c = *current++;
0963 unicode *= 16;
0964 if (c >= '0' && c <= '9')
0965 unicode += c - '0';
0966 else if (c >= 'a' && c <= 'f')
0967 unicode += c - 'a' + 10;
0968 else if (c >= 'A' && c <= 'F')
0969 unicode += c - 'A' + 10;
0970 else
0971 return addError(
0972 "Bad unicode escape sequence in string: hexadecimal digit expected.",
0973 token,
0974 current);
0975 }
0976 ret_unicode = static_cast<unsigned int>(unicode);
0977 return true;
0978 }
0979
0980 bool
0981 Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
0982 ErrorInfo info;
0983 info.token_ = token;
0984 info.message_ = message;
0985 info.extra_ = extra;
0986 errors_.push_back(info);
0987 return false;
0988 }
0989
0990 bool Reader::recoverFromError(TokenType skipUntilToken) {
0991 size_t const errorCount = errors_.size();
0992 Token skip;
0993 for (;;) {
0994 if (!readToken(skip))
0995 errors_.resize(errorCount);
0996 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
0997 break;
0998 }
0999 errors_.resize(errorCount);
1000 return false;
1001 }
1002
1003 bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
1004 Token& token,
1005 TokenType skipUntilToken) {
1006 addError(message, token);
1007 return recoverFromError(skipUntilToken);
1008 }
1009
1010 Value& Reader::currentValue() { return *(nodes_.top()); }
1011
1012 Reader::Char Reader::getNextChar() {
1013 if (current_ == end_)
1014 return 0;
1015 return *current_++;
1016 }
1017
1018 void Reader::getLocationLineAndColumn(Location location,
1019 int& line,
1020 int& column) const {
1021 Location current = begin_;
1022 Location lastLineStart = current;
1023 line = 0;
1024 while (current < location && current != end_) {
1025 Char c = *current++;
1026 if (c == '\r') {
1027 if (*current == '\n')
1028 ++current;
1029 lastLineStart = current;
1030 ++line;
1031 } else if (c == '\n') {
1032 lastLineStart = current;
1033 ++line;
1034 }
1035 }
1036
1037 column = int(location - lastLineStart) + 1;
1038 ++line;
1039 }
1040
1041 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
1042 int line, column;
1043 getLocationLineAndColumn(location, line, column);
1044 char buffer[18 + 16 + 16 + 1];
1045 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
1046 return buffer;
1047 }
1048
1049
1050 JSONCPP_STRING Reader::getFormatedErrorMessages() const {
1051 return getFormattedErrorMessages();
1052 }
1053
1054 JSONCPP_STRING Reader::getFormattedErrorMessages() const {
1055 JSONCPP_STRING formattedMessage;
1056 for (Errors::const_iterator itError = errors_.begin();
1057 itError != errors_.end();
1058 ++itError) {
1059 const ErrorInfo& error = *itError;
1060 formattedMessage +=
1061 "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
1062 formattedMessage += " " + error.message_ + "\n";
1063 if (error.extra_)
1064 formattedMessage +=
1065 "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
1066 }
1067 return formattedMessage;
1068 }
1069
1070 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
1071 std::vector<Reader::StructuredError> allErrors;
1072 for (Errors::const_iterator itError = errors_.begin();
1073 itError != errors_.end();
1074 ++itError) {
1075 const ErrorInfo& error = *itError;
1076 Reader::StructuredError structured;
1077 structured.offset_start = error.token_.start_ - begin_;
1078 structured.offset_limit = error.token_.end_ - begin_;
1079 structured.message = error.message_;
1080 allErrors.push_back(structured);
1081 }
1082 return allErrors;
1083 }
1084
1085 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
1086 ptrdiff_t const length = end_ - begin_;
1087 if(value.getOffsetStart() > length
1088 || value.getOffsetLimit() > length)
1089 return false;
1090 Token token;
1091 token.type_ = tokenError;
1092 token.start_ = begin_ + value.getOffsetStart();
1093 token.end_ = end_ + value.getOffsetLimit();
1094 ErrorInfo info;
1095 info.token_ = token;
1096 info.message_ = message;
1097 info.extra_ = 0;
1098 errors_.push_back(info);
1099 return true;
1100 }
1101
1102 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
1103 ptrdiff_t const length = end_ - begin_;
1104 if(value.getOffsetStart() > length
1105 || value.getOffsetLimit() > length
1106 || extra.getOffsetLimit() > length)
1107 return false;
1108 Token token;
1109 token.type_ = tokenError;
1110 token.start_ = begin_ + value.getOffsetStart();
1111 token.end_ = begin_ + value.getOffsetLimit();
1112 ErrorInfo info;
1113 info.token_ = token;
1114 info.message_ = message;
1115 info.extra_ = begin_ + extra.getOffsetStart();
1116 errors_.push_back(info);
1117 return true;
1118 }
1119
1120 bool Reader::good() const {
1121 return !errors_.size();
1122 }
1123
1124
1125 class OurFeatures {
1126 public:
1127 static OurFeatures all();
1128 bool allowComments_;
1129 bool strictRoot_;
1130 bool allowDroppedNullPlaceholders_;
1131 bool allowNumericKeys_;
1132 bool allowSingleQuotes_;
1133 bool failIfExtra_;
1134 bool rejectDupKeys_;
1135 bool allowSpecialFloats_;
1136 int stackLimit_;
1137 };
1138
1139
1140
1141
1142 OurFeatures OurFeatures::all() { return OurFeatures(); }
1143
1144
1145
1146
1147
1148 class OurReader {
1149 public:
1150 typedef char Char;
1151 typedef const Char* Location;
1152 struct StructuredError {
1153 ptrdiff_t offset_start;
1154 ptrdiff_t offset_limit;
1155 JSONCPP_STRING message;
1156 };
1157
1158 OurReader(OurFeatures const& features);
1159 bool parse(const char* beginDoc,
1160 const char* endDoc,
1161 Value& root,
1162 bool collectComments = true);
1163 JSONCPP_STRING getFormattedErrorMessages() const;
1164 std::vector<StructuredError> getStructuredErrors() const;
1165 bool pushError(const Value& value, const JSONCPP_STRING& message);
1166 bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
1167 bool good() const;
1168
1169 private:
1170 OurReader(OurReader const&);
1171 void operator=(OurReader const&);
1172
1173 enum TokenType {
1174 tokenEndOfStream = 0,
1175 tokenObjectBegin,
1176 tokenObjectEnd,
1177 tokenArrayBegin,
1178 tokenArrayEnd,
1179 tokenString,
1180 tokenNumber,
1181 tokenTrue,
1182 tokenFalse,
1183 tokenNull,
1184 tokenNaN,
1185 tokenPosInf,
1186 tokenNegInf,
1187 tokenArraySeparator,
1188 tokenMemberSeparator,
1189 tokenComment,
1190 tokenError
1191 };
1192
1193 class Token {
1194 public:
1195 TokenType type_;
1196 Location start_;
1197 Location end_;
1198 };
1199
1200 class ErrorInfo {
1201 public:
1202 Token token_;
1203 JSONCPP_STRING message_;
1204 Location extra_;
1205 };
1206
1207 typedef std::deque<ErrorInfo> Errors;
1208
1209 bool readToken(Token& token);
1210 void skipSpaces();
1211 bool match(Location pattern, int patternLength);
1212 bool readComment();
1213 bool readCStyleComment();
1214 bool readCppStyleComment();
1215 bool readString();
1216 bool readStringSingleQuote();
1217 bool readNumber(bool checkInf);
1218 bool readValue();
1219 bool readObject(Token& token);
1220 bool readArray(Token& token);
1221 bool decodeNumber(Token& token);
1222 bool decodeNumber(Token& token, Value& decoded);
1223 bool decodeString(Token& token);
1224 bool decodeString(Token& token, JSONCPP_STRING& decoded);
1225 bool decodeDouble(Token& token);
1226 bool decodeDouble(Token& token, Value& decoded);
1227 bool decodeUnicodeCodePoint(Token& token,
1228 Location& current,
1229 Location end,
1230 unsigned int& unicode);
1231 bool decodeUnicodeEscapeSequence(Token& token,
1232 Location& current,
1233 Location end,
1234 unsigned int& unicode);
1235 bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
1236 bool recoverFromError(TokenType skipUntilToken);
1237 bool addErrorAndRecover(const JSONCPP_STRING& message,
1238 Token& token,
1239 TokenType skipUntilToken);
1240 void skipUntilSpace();
1241 Value& currentValue();
1242 Char getNextChar();
1243 void
1244 getLocationLineAndColumn(Location location, int& line, int& column) const;
1245 JSONCPP_STRING getLocationLineAndColumn(Location location) const;
1246 void addComment(Location begin, Location end, CommentPlacement placement);
1247 void skipCommentTokens(Token& token);
1248
1249 static JSONCPP_STRING normalizeEOL(Location begin, Location end);
1250 static bool containsNewLine(Location begin, Location end);
1251
1252 typedef std::stack<Value*> Nodes;
1253 Nodes nodes_;
1254 Errors errors_;
1255 JSONCPP_STRING document_;
1256 Location begin_;
1257 Location end_;
1258 Location current_;
1259 Location lastValueEnd_;
1260 Value* lastValue_;
1261 JSONCPP_STRING commentsBefore_;
1262
1263 OurFeatures const features_;
1264 bool collectComments_;
1265 };
1266
1267
1268
1269 bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
1270 for (; begin < end; ++begin)
1271 if (*begin == '\n' || *begin == '\r')
1272 return true;
1273 return false;
1274 }
1275
1276 OurReader::OurReader(OurFeatures const& features)
1277 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1278 lastValue_(), commentsBefore_(),
1279 features_(features), collectComments_() {
1280 }
1281
1282 bool OurReader::parse(const char* beginDoc,
1283 const char* endDoc,
1284 Value& root,
1285 bool collectComments) {
1286 if (!features_.allowComments_) {
1287 collectComments = false;
1288 }
1289
1290 begin_ = beginDoc;
1291 end_ = endDoc;
1292 collectComments_ = collectComments;
1293 current_ = begin_;
1294 lastValueEnd_ = 0;
1295 lastValue_ = 0;
1296 commentsBefore_.clear();
1297 errors_.clear();
1298 while (!nodes_.empty())
1299 nodes_.pop();
1300 nodes_.push(&root);
1301
1302 bool successful = readValue();
1303 Token token;
1304 skipCommentTokens(token);
1305 if (features_.failIfExtra_) {
1306 if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
1307 addError("Extra non-whitespace after JSON value.", token);
1308 return false;
1309 }
1310 }
1311 if (collectComments_ && !commentsBefore_.empty())
1312 root.setComment(commentsBefore_, commentAfter);
1313 if (features_.strictRoot_) {
1314 if (!root.isArray() && !root.isObject()) {
1315
1316
1317 token.type_ = tokenError;
1318 token.start_ = beginDoc;
1319 token.end_ = endDoc;
1320 addError(
1321 "A valid JSON document must be either an array or an object value.",
1322 token);
1323 return false;
1324 }
1325 }
1326 return successful;
1327 }
1328
1329 bool OurReader::readValue() {
1330
1331 if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
1332 Token token;
1333 skipCommentTokens(token);
1334 bool successful = true;
1335
1336 if (collectComments_ && !commentsBefore_.empty()) {
1337 currentValue().setComment(commentsBefore_, commentBefore);
1338 commentsBefore_.clear();
1339 }
1340
1341 switch (token.type_) {
1342 case tokenObjectBegin:
1343 successful = readObject(token);
1344 currentValue().setOffsetLimit(current_ - begin_);
1345 break;
1346 case tokenArrayBegin:
1347 successful = readArray(token);
1348 currentValue().setOffsetLimit(current_ - begin_);
1349 break;
1350 case tokenNumber:
1351 successful = decodeNumber(token);
1352 break;
1353 case tokenString:
1354 successful = decodeString(token);
1355 break;
1356 case tokenTrue:
1357 {
1358 Value v(true);
1359 currentValue().swapPayload(v);
1360 currentValue().setOffsetStart(token.start_ - begin_);
1361 currentValue().setOffsetLimit(token.end_ - begin_);
1362 }
1363 break;
1364 case tokenFalse:
1365 {
1366 Value v(false);
1367 currentValue().swapPayload(v);
1368 currentValue().setOffsetStart(token.start_ - begin_);
1369 currentValue().setOffsetLimit(token.end_ - begin_);
1370 }
1371 break;
1372 case tokenNull:
1373 {
1374 Value v;
1375 currentValue().swapPayload(v);
1376 currentValue().setOffsetStart(token.start_ - begin_);
1377 currentValue().setOffsetLimit(token.end_ - begin_);
1378 }
1379 break;
1380 case tokenNaN:
1381 {
1382 Value v(std::numeric_limits<double>::quiet_NaN());
1383 currentValue().swapPayload(v);
1384 currentValue().setOffsetStart(token.start_ - begin_);
1385 currentValue().setOffsetLimit(token.end_ - begin_);
1386 }
1387 break;
1388 case tokenPosInf:
1389 {
1390 Value v(std::numeric_limits<double>::infinity());
1391 currentValue().swapPayload(v);
1392 currentValue().setOffsetStart(token.start_ - begin_);
1393 currentValue().setOffsetLimit(token.end_ - begin_);
1394 }
1395 break;
1396 case tokenNegInf:
1397 {
1398 Value v(-std::numeric_limits<double>::infinity());
1399 currentValue().swapPayload(v);
1400 currentValue().setOffsetStart(token.start_ - begin_);
1401 currentValue().setOffsetLimit(token.end_ - begin_);
1402 }
1403 break;
1404 case tokenArraySeparator:
1405 case tokenObjectEnd:
1406 case tokenArrayEnd:
1407 if (features_.allowDroppedNullPlaceholders_) {
1408
1409
1410 current_--;
1411 Value v;
1412 currentValue().swapPayload(v);
1413 currentValue().setOffsetStart(current_ - begin_ - 1);
1414 currentValue().setOffsetLimit(current_ - begin_);
1415 break;
1416 }
1417 default:
1418 currentValue().setOffsetStart(token.start_ - begin_);
1419 currentValue().setOffsetLimit(token.end_ - begin_);
1420 return addError("Syntax error: value, object or array expected.", token);
1421 }
1422
1423 if (collectComments_) {
1424 lastValueEnd_ = current_;
1425 lastValue_ = ¤tValue();
1426 }
1427
1428 return successful;
1429 }
1430
1431 void OurReader::skipCommentTokens(Token& token) {
1432 if (features_.allowComments_) {
1433 do {
1434 readToken(token);
1435 } while (token.type_ == tokenComment);
1436 } else {
1437 readToken(token);
1438 }
1439 }
1440
1441 bool OurReader::readToken(Token& token) {
1442 skipSpaces();
1443 token.start_ = current_;
1444 Char c = getNextChar();
1445 bool ok = true;
1446 switch (c) {
1447 case '{':
1448 token.type_ = tokenObjectBegin;
1449 break;
1450 case '}':
1451 token.type_ = tokenObjectEnd;
1452 break;
1453 case '[':
1454 token.type_ = tokenArrayBegin;
1455 break;
1456 case ']':
1457 token.type_ = tokenArrayEnd;
1458 break;
1459 case '"':
1460 token.type_ = tokenString;
1461 ok = readString();
1462 break;
1463 case '\'':
1464 if (features_.allowSingleQuotes_) {
1465 token.type_ = tokenString;
1466 ok = readStringSingleQuote();
1467 break;
1468 }
1469 case '/':
1470 token.type_ = tokenComment;
1471 ok = readComment();
1472 break;
1473 case '0':
1474 case '1':
1475 case '2':
1476 case '3':
1477 case '4':
1478 case '5':
1479 case '6':
1480 case '7':
1481 case '8':
1482 case '9':
1483 token.type_ = tokenNumber;
1484 readNumber(false);
1485 break;
1486 case '-':
1487 if (readNumber(true)) {
1488 token.type_ = tokenNumber;
1489 } else {
1490 token.type_ = tokenNegInf;
1491 ok = features_.allowSpecialFloats_ && match("nfinity", 7);
1492 }
1493 break;
1494 case 't':
1495 token.type_ = tokenTrue;
1496 ok = match("rue", 3);
1497 break;
1498 case 'f':
1499 token.type_ = tokenFalse;
1500 ok = match("alse", 4);
1501 break;
1502 case 'n':
1503 token.type_ = tokenNull;
1504 ok = match("ull", 3);
1505 break;
1506 case 'N':
1507 if (features_.allowSpecialFloats_) {
1508 token.type_ = tokenNaN;
1509 ok = match("aN", 2);
1510 } else {
1511 ok = false;
1512 }
1513 break;
1514 case 'I':
1515 if (features_.allowSpecialFloats_) {
1516 token.type_ = tokenPosInf;
1517 ok = match("nfinity", 7);
1518 } else {
1519 ok = false;
1520 }
1521 break;
1522 case ',':
1523 token.type_ = tokenArraySeparator;
1524 break;
1525 case ':':
1526 token.type_ = tokenMemberSeparator;
1527 break;
1528 case 0:
1529 token.type_ = tokenEndOfStream;
1530 break;
1531 default:
1532 ok = false;
1533 break;
1534 }
1535 if (!ok)
1536 token.type_ = tokenError;
1537 token.end_ = current_;
1538 return true;
1539 }
1540
1541 void OurReader::skipSpaces() {
1542 while (current_ != end_) {
1543 Char c = *current_;
1544 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
1545 ++current_;
1546 else
1547 break;
1548 }
1549 }
1550
1551 bool OurReader::match(Location pattern, int patternLength) {
1552 if (end_ - current_ < patternLength)
1553 return false;
1554 int index = patternLength;
1555 while (index--)
1556 if (current_[index] != pattern[index])
1557 return false;
1558 current_ += patternLength;
1559 return true;
1560 }
1561
1562 bool OurReader::readComment() {
1563 Location commentBegin = current_ - 1;
1564 Char c = getNextChar();
1565 bool successful = false;
1566 if (c == '*')
1567 successful = readCStyleComment();
1568 else if (c == '/')
1569 successful = readCppStyleComment();
1570 if (!successful)
1571 return false;
1572
1573 if (collectComments_) {
1574 CommentPlacement placement = commentBefore;
1575 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
1576 if (c != '*' || !containsNewLine(commentBegin, current_))
1577 placement = commentAfterOnSameLine;
1578 }
1579
1580 addComment(commentBegin, current_, placement);
1581 }
1582 return true;
1583 }
1584
1585 JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
1586 JSONCPP_STRING normalized;
1587 normalized.reserve(static_cast<size_t>(end - begin));
1588 OurReader::Location current = begin;
1589 while (current != end) {
1590 char c = *current++;
1591 if (c == '\r') {
1592 if (current != end && *current == '\n')
1593
1594 ++current;
1595
1596 normalized += '\n';
1597 } else {
1598 normalized += c;
1599 }
1600 }
1601 return normalized;
1602 }
1603
1604 void
1605 OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
1606 assert(collectComments_);
1607 const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
1608 if (placement == commentAfterOnSameLine) {
1609 assert(lastValue_ != 0);
1610 lastValue_->setComment(normalized, placement);
1611 } else {
1612 commentsBefore_ += normalized;
1613 }
1614 }
1615
1616 bool OurReader::readCStyleComment() {
1617 while ((current_ + 1) < end_) {
1618 Char c = getNextChar();
1619 if (c == '*' && *current_ == '/')
1620 break;
1621 }
1622 return getNextChar() == '/';
1623 }
1624
1625 bool OurReader::readCppStyleComment() {
1626 while (current_ != end_) {
1627 Char c = getNextChar();
1628 if (c == '\n')
1629 break;
1630 if (c == '\r') {
1631
1632 if (current_ != end_ && *current_ == '\n')
1633 getNextChar();
1634
1635 break;
1636 }
1637 }
1638 return true;
1639 }
1640
1641 bool OurReader::readNumber(bool checkInf) {
1642 const char *p = current_;
1643 if (checkInf && p != end_ && *p == 'I') {
1644 current_ = ++p;
1645 return false;
1646 }
1647 char c = '0';
1648
1649 while (c >= '0' && c <= '9')
1650 c = (current_ = p) < end_ ? *p++ : '\0';
1651
1652 if (c == '.') {
1653 c = (current_ = p) < end_ ? *p++ : '\0';
1654 while (c >= '0' && c <= '9')
1655 c = (current_ = p) < end_ ? *p++ : '\0';
1656 }
1657
1658 if (c == 'e' || c == 'E') {
1659 c = (current_ = p) < end_ ? *p++ : '\0';
1660 if (c == '+' || c == '-')
1661 c = (current_ = p) < end_ ? *p++ : '\0';
1662 while (c >= '0' && c <= '9')
1663 c = (current_ = p) < end_ ? *p++ : '\0';
1664 }
1665 return true;
1666 }
1667 bool OurReader::readString() {
1668 Char c = 0;
1669 while (current_ != end_) {
1670 c = getNextChar();
1671 if (c == '\\')
1672 getNextChar();
1673 else if (c == '"')
1674 break;
1675 }
1676 return c == '"';
1677 }
1678
1679
1680 bool OurReader::readStringSingleQuote() {
1681 Char c = 0;
1682 while (current_ != end_) {
1683 c = getNextChar();
1684 if (c == '\\')
1685 getNextChar();
1686 else if (c == '\'')
1687 break;
1688 }
1689 return c == '\'';
1690 }
1691
1692 bool OurReader::readObject(Token& tokenStart) {
1693 Token tokenName;
1694 JSONCPP_STRING name;
1695 Value init(objectValue);
1696 currentValue().swapPayload(init);
1697 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1698 while (readToken(tokenName)) {
1699 bool initialTokenOk = true;
1700 while (tokenName.type_ == tokenComment && initialTokenOk)
1701 initialTokenOk = readToken(tokenName);
1702 if (!initialTokenOk)
1703 break;
1704 if (tokenName.type_ == tokenObjectEnd && name.empty())
1705 return true;
1706 name.clear();
1707 if (tokenName.type_ == tokenString) {
1708 if (!decodeString(tokenName, name))
1709 return recoverFromError(tokenObjectEnd);
1710 } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
1711 Value numberName;
1712 if (!decodeNumber(tokenName, numberName))
1713 return recoverFromError(tokenObjectEnd);
1714 name = numberName.asString();
1715 } else {
1716 break;
1717 }
1718
1719 Token colon;
1720 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
1721 return addErrorAndRecover(
1722 "Missing ':' after object member name", colon, tokenObjectEnd);
1723 }
1724 if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
1725 if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
1726 JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
1727 return addErrorAndRecover(
1728 msg, tokenName, tokenObjectEnd);
1729 }
1730 Value& value = currentValue()[name];
1731 nodes_.push(&value);
1732 bool ok = readValue();
1733 nodes_.pop();
1734 if (!ok)
1735 return recoverFromError(tokenObjectEnd);
1736
1737 Token comma;
1738 if (!readToken(comma) ||
1739 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1740 comma.type_ != tokenComment)) {
1741 return addErrorAndRecover(
1742 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1743 }
1744 bool finalizeTokenOk = true;
1745 while (comma.type_ == tokenComment && finalizeTokenOk)
1746 finalizeTokenOk = readToken(comma);
1747 if (comma.type_ == tokenObjectEnd)
1748 return true;
1749 }
1750 return addErrorAndRecover(
1751 "Missing '}' or object member name", tokenName, tokenObjectEnd);
1752 }
1753
1754 bool OurReader::readArray(Token& tokenStart) {
1755 Value init(arrayValue);
1756 currentValue().swapPayload(init);
1757 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1758 skipSpaces();
1759 if (current_ != end_ && *current_ == ']')
1760 {
1761 Token endArray;
1762 readToken(endArray);
1763 return true;
1764 }
1765 int index = 0;
1766 for (;;) {
1767 Value& value = currentValue()[index++];
1768 nodes_.push(&value);
1769 bool ok = readValue();
1770 nodes_.pop();
1771 if (!ok)
1772 return recoverFromError(tokenArrayEnd);
1773
1774 Token token;
1775
1776 ok = readToken(token);
1777 while (token.type_ == tokenComment && ok) {
1778 ok = readToken(token);
1779 }
1780 bool badTokenType =
1781 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1782 if (!ok || badTokenType) {
1783 return addErrorAndRecover(
1784 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1785 }
1786 if (token.type_ == tokenArrayEnd)
1787 break;
1788 }
1789 return true;
1790 }
1791
1792 bool OurReader::decodeNumber(Token& token) {
1793 Value decoded;
1794 if (!decodeNumber(token, decoded))
1795 return false;
1796 currentValue().swapPayload(decoded);
1797 currentValue().setOffsetStart(token.start_ - begin_);
1798 currentValue().setOffsetLimit(token.end_ - begin_);
1799 return true;
1800 }
1801
1802 bool OurReader::decodeNumber(Token& token, Value& decoded) {
1803
1804
1805
1806 Location current = token.start_;
1807 bool isNegative = *current == '-';
1808 if (isNegative)
1809 ++current;
1810
1811 Value::LargestUInt maxIntegerValue =
1812 isNegative ? Value::LargestUInt(-Value::minLargestInt)
1813 : Value::maxLargestUInt;
1814 Value::LargestUInt threshold = maxIntegerValue / 10;
1815 Value::LargestUInt value = 0;
1816 while (current < token.end_) {
1817 Char c = *current++;
1818 if (c < '0' || c > '9')
1819 return decodeDouble(token, decoded);
1820 Value::UInt digit(static_cast<Value::UInt>(c - '0'));
1821 if (value >= threshold) {
1822
1823
1824
1825
1826 if (value > threshold || current != token.end_ ||
1827 digit > maxIntegerValue % 10) {
1828 return decodeDouble(token, decoded);
1829 }
1830 }
1831 value = value * 10 + digit;
1832 }
1833 if (isNegative)
1834 decoded = -Value::LargestInt(value);
1835 else if (value <= Value::LargestUInt(Value::maxInt))
1836 decoded = Value::LargestInt(value);
1837 else
1838 decoded = value;
1839 return true;
1840 }
1841
1842 bool OurReader::decodeDouble(Token& token) {
1843 Value decoded;
1844 if (!decodeDouble(token, decoded))
1845 return false;
1846 currentValue().swapPayload(decoded);
1847 currentValue().setOffsetStart(token.start_ - begin_);
1848 currentValue().setOffsetLimit(token.end_ - begin_);
1849 return true;
1850 }
1851
1852 bool OurReader::decodeDouble(Token& token, Value& decoded) {
1853 double value = 0;
1854 const int bufferSize = 32;
1855 int count;
1856 ptrdiff_t const length = token.end_ - token.start_;
1857
1858
1859 if (length < 0) {
1860 return addError("Unable to parse token length", token);
1861 }
1862 size_t const ulength = static_cast<size_t>(length);
1863
1864
1865
1866
1867
1868
1869 char format[] = "%lf";
1870
1871 if (length <= bufferSize) {
1872 Char buffer[bufferSize + 1];
1873 memcpy(buffer, token.start_, ulength);
1874 buffer[length] = 0;
1875 fixNumericLocaleInput(buffer, buffer + length);
1876 count = sscanf(buffer, format, &value);
1877 } else {
1878 JSONCPP_STRING buffer(token.start_, token.end_);
1879 count = sscanf(buffer.c_str(), format, &value);
1880 }
1881
1882 if (count != 1)
1883 return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
1884 "' is not a number.",
1885 token);
1886 decoded = value;
1887 return true;
1888 }
1889
1890 bool OurReader::decodeString(Token& token) {
1891 JSONCPP_STRING decoded_string;
1892 if (!decodeString(token, decoded_string))
1893 return false;
1894 Value decoded(decoded_string);
1895 currentValue().swapPayload(decoded);
1896 currentValue().setOffsetStart(token.start_ - begin_);
1897 currentValue().setOffsetLimit(token.end_ - begin_);
1898 return true;
1899 }
1900
1901 bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
1902 decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
1903 Location current = token.start_ + 1;
1904 Location end = token.end_ - 1;
1905 while (current != end) {
1906 Char c = *current++;
1907 if (c == '"')
1908 break;
1909 else if (c == '\\') {
1910 if (current == end)
1911 return addError("Empty escape sequence in string", token, current);
1912 Char escape = *current++;
1913 switch (escape) {
1914 case '"':
1915 decoded += '"';
1916 break;
1917 case '/':
1918 decoded += '/';
1919 break;
1920 case '\\':
1921 decoded += '\\';
1922 break;
1923 case 'b':
1924 decoded += '\b';
1925 break;
1926 case 'f':
1927 decoded += '\f';
1928 break;
1929 case 'n':
1930 decoded += '\n';
1931 break;
1932 case 'r':
1933 decoded += '\r';
1934 break;
1935 case 't':
1936 decoded += '\t';
1937 break;
1938 case 'u': {
1939 unsigned int unicode;
1940 if (!decodeUnicodeCodePoint(token, current, end, unicode))
1941 return false;
1942 decoded += codePointToUTF8(unicode);
1943 } break;
1944 default:
1945 return addError("Bad escape sequence in string", token, current);
1946 }
1947 } else {
1948 decoded += c;
1949 }
1950 }
1951 return true;
1952 }
1953
1954 bool OurReader::decodeUnicodeCodePoint(Token& token,
1955 Location& current,
1956 Location end,
1957 unsigned int& unicode) {
1958
1959 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
1960 return false;
1961 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
1962
1963 if (end - current < 6)
1964 return addError(
1965 "additional six characters expected to parse unicode surrogate pair.",
1966 token,
1967 current);
1968 unsigned int surrogatePair;
1969 if (*(current++) == '\\' && *(current++) == 'u') {
1970 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
1971 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1972 } else
1973 return false;
1974 } else
1975 return addError("expecting another \\u token to begin the second half of "
1976 "a unicode surrogate pair",
1977 token,
1978 current);
1979 }
1980 return true;
1981 }
1982
1983 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
1984 Location& current,
1985 Location end,
1986 unsigned int& ret_unicode) {
1987 if (end - current < 4)
1988 return addError(
1989 "Bad unicode escape sequence in string: four digits expected.",
1990 token,
1991 current);
1992 int unicode = 0;
1993 for (int index = 0; index < 4; ++index) {
1994 Char c = *current++;
1995 unicode *= 16;
1996 if (c >= '0' && c <= '9')
1997 unicode += c - '0';
1998 else if (c >= 'a' && c <= 'f')
1999 unicode += c - 'a' + 10;
2000 else if (c >= 'A' && c <= 'F')
2001 unicode += c - 'A' + 10;
2002 else
2003 return addError(
2004 "Bad unicode escape sequence in string: hexadecimal digit expected.",
2005 token,
2006 current);
2007 }
2008 ret_unicode = static_cast<unsigned int>(unicode);
2009 return true;
2010 }
2011
2012 bool
2013 OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
2014 ErrorInfo info;
2015 info.token_ = token;
2016 info.message_ = message;
2017 info.extra_ = extra;
2018 errors_.push_back(info);
2019 return false;
2020 }
2021
2022 bool OurReader::recoverFromError(TokenType skipUntilToken) {
2023 size_t errorCount = errors_.size();
2024 Token skip;
2025 for (;;) {
2026 if (!readToken(skip))
2027 errors_.resize(errorCount);
2028 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
2029 break;
2030 }
2031 errors_.resize(errorCount);
2032 return false;
2033 }
2034
2035 bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
2036 Token& token,
2037 TokenType skipUntilToken) {
2038 addError(message, token);
2039 return recoverFromError(skipUntilToken);
2040 }
2041
2042 Value& OurReader::currentValue() { return *(nodes_.top()); }
2043
2044 OurReader::Char OurReader::getNextChar() {
2045 if (current_ == end_)
2046 return 0;
2047 return *current_++;
2048 }
2049
2050 void OurReader::getLocationLineAndColumn(Location location,
2051 int& line,
2052 int& column) const {
2053 Location current = begin_;
2054 Location lastLineStart = current;
2055 line = 0;
2056 while (current < location && current != end_) {
2057 Char c = *current++;
2058 if (c == '\r') {
2059 if (*current == '\n')
2060 ++current;
2061 lastLineStart = current;
2062 ++line;
2063 } else if (c == '\n') {
2064 lastLineStart = current;
2065 ++line;
2066 }
2067 }
2068
2069 column = int(location - lastLineStart) + 1;
2070 ++line;
2071 }
2072
2073 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
2074 int line, column;
2075 getLocationLineAndColumn(location, line, column);
2076 char buffer[18 + 16 + 16 + 1];
2077 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
2078 return buffer;
2079 }
2080
2081 JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
2082 JSONCPP_STRING formattedMessage;
2083 for (Errors::const_iterator itError = errors_.begin();
2084 itError != errors_.end();
2085 ++itError) {
2086 const ErrorInfo& error = *itError;
2087 formattedMessage +=
2088 "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
2089 formattedMessage += " " + error.message_ + "\n";
2090 if (error.extra_)
2091 formattedMessage +=
2092 "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
2093 }
2094 return formattedMessage;
2095 }
2096
2097 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
2098 std::vector<OurReader::StructuredError> allErrors;
2099 for (Errors::const_iterator itError = errors_.begin();
2100 itError != errors_.end();
2101 ++itError) {
2102 const ErrorInfo& error = *itError;
2103 OurReader::StructuredError structured;
2104 structured.offset_start = error.token_.start_ - begin_;
2105 structured.offset_limit = error.token_.end_ - begin_;
2106 structured.message = error.message_;
2107 allErrors.push_back(structured);
2108 }
2109 return allErrors;
2110 }
2111
2112 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
2113 ptrdiff_t length = end_ - begin_;
2114 if(value.getOffsetStart() > length
2115 || value.getOffsetLimit() > length)
2116 return false;
2117 Token token;
2118 token.type_ = tokenError;
2119 token.start_ = begin_ + value.getOffsetStart();
2120 token.end_ = end_ + value.getOffsetLimit();
2121 ErrorInfo info;
2122 info.token_ = token;
2123 info.message_ = message;
2124 info.extra_ = 0;
2125 errors_.push_back(info);
2126 return true;
2127 }
2128
2129 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
2130 ptrdiff_t length = end_ - begin_;
2131 if(value.getOffsetStart() > length
2132 || value.getOffsetLimit() > length
2133 || extra.getOffsetLimit() > length)
2134 return false;
2135 Token token;
2136 token.type_ = tokenError;
2137 token.start_ = begin_ + value.getOffsetStart();
2138 token.end_ = begin_ + value.getOffsetLimit();
2139 ErrorInfo info;
2140 info.token_ = token;
2141 info.message_ = message;
2142 info.extra_ = begin_ + extra.getOffsetStart();
2143 errors_.push_back(info);
2144 return true;
2145 }
2146
2147 bool OurReader::good() const {
2148 return !errors_.size();
2149 }
2150
2151
2152 class OurCharReader : public CharReader {
2153 bool const collectComments_;
2154 OurReader reader_;
2155 public:
2156 OurCharReader(
2157 bool collectComments,
2158 OurFeatures const& features)
2159 : collectComments_(collectComments)
2160 , reader_(features)
2161 {}
2162 bool parse(
2163 char const* beginDoc, char const* endDoc,
2164 Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
2165 bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
2166 if (errs) {
2167 *errs = reader_.getFormattedErrorMessages();
2168 }
2169 return ok;
2170 }
2171 };
2172
2173 CharReaderBuilder::CharReaderBuilder()
2174 {
2175 setDefaults(&settings_);
2176 }
2177 CharReaderBuilder::~CharReaderBuilder()
2178 {}
2179 CharReader* CharReaderBuilder::newCharReader() const
2180 {
2181 bool collectComments = settings_["collectComments"].asBool();
2182 OurFeatures features = OurFeatures::all();
2183 features.allowComments_ = settings_["allowComments"].asBool();
2184 features.strictRoot_ = settings_["strictRoot"].asBool();
2185 features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
2186 features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
2187 features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
2188 features.stackLimit_ = settings_["stackLimit"].asInt();
2189 features.failIfExtra_ = settings_["failIfExtra"].asBool();
2190 features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
2191 features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
2192 return new OurCharReader(collectComments, features);
2193 }
2194 static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
2195 {
2196 valid_keys->clear();
2197 valid_keys->insert("collectComments");
2198 valid_keys->insert("allowComments");
2199 valid_keys->insert("strictRoot");
2200 valid_keys->insert("allowDroppedNullPlaceholders");
2201 valid_keys->insert("allowNumericKeys");
2202 valid_keys->insert("allowSingleQuotes");
2203 valid_keys->insert("stackLimit");
2204 valid_keys->insert("failIfExtra");
2205 valid_keys->insert("rejectDupKeys");
2206 valid_keys->insert("allowSpecialFloats");
2207 }
2208 bool CharReaderBuilder::validate(Json::Value* invalid) const
2209 {
2210 Json::Value my_invalid;
2211 if (!invalid) invalid = &my_invalid;
2212 Json::Value& inv = *invalid;
2213 std::set<JSONCPP_STRING> valid_keys;
2214 getValidReaderKeys(&valid_keys);
2215 Value::Members keys = settings_.getMemberNames();
2216 size_t n = keys.size();
2217 for (size_t i = 0; i < n; ++i) {
2218 JSONCPP_STRING const& key = keys[i];
2219 if (valid_keys.find(key) == valid_keys.end()) {
2220 inv[key] = settings_[key];
2221 }
2222 }
2223 return 0u == inv.size();
2224 }
2225 Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
2226 {
2227 return settings_[key];
2228 }
2229
2230 void CharReaderBuilder::strictMode(Json::Value* settings)
2231 {
2232
2233 (*settings)["allowComments"] = false;
2234 (*settings)["strictRoot"] = true;
2235 (*settings)["allowDroppedNullPlaceholders"] = false;
2236 (*settings)["allowNumericKeys"] = false;
2237 (*settings)["allowSingleQuotes"] = false;
2238 (*settings)["stackLimit"] = 1000;
2239 (*settings)["failIfExtra"] = true;
2240 (*settings)["rejectDupKeys"] = true;
2241 (*settings)["allowSpecialFloats"] = false;
2242
2243 }
2244
2245 void CharReaderBuilder::setDefaults(Json::Value* settings)
2246 {
2247
2248 (*settings)["collectComments"] = true;
2249 (*settings)["allowComments"] = true;
2250 (*settings)["strictRoot"] = false;
2251 (*settings)["allowDroppedNullPlaceholders"] = false;
2252 (*settings)["allowNumericKeys"] = false;
2253 (*settings)["allowSingleQuotes"] = false;
2254 (*settings)["stackLimit"] = 1000;
2255 (*settings)["failIfExtra"] = false;
2256 (*settings)["rejectDupKeys"] = false;
2257 (*settings)["allowSpecialFloats"] = false;
2258
2259 }
2260
2261
2262
2263
2264 bool parseFromStream(
2265 CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
2266 Value* root, JSONCPP_STRING* errs)
2267 {
2268 JSONCPP_OSTRINGSTREAM ssin;
2269 ssin << sin.rdbuf();
2270 JSONCPP_STRING doc = ssin.str();
2271 char const* begin = doc.data();
2272 char const* end = begin + doc.size();
2273
2274 CharReaderPtr const reader(fact.newCharReader());
2275 return reader->parse(begin, end, root, errs);
2276 }
2277
2278 JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
2279 CharReaderBuilder b;
2280 JSONCPP_STRING errs;
2281 bool ok = parseFromStream(b, sin, &root, &errs);
2282 if (!ok) {
2283 throwRuntimeError(errs);
2284 }
2285 return sin;
2286 }
2287
2288 }
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310 namespace Json {
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320 ValueIteratorBase::ValueIteratorBase()
2321 : current_(), isNull_(true) {
2322 }
2323
2324 ValueIteratorBase::ValueIteratorBase(
2325 const Value::ObjectValues::iterator& current)
2326 : current_(current), isNull_(false) {}
2327
2328 Value& ValueIteratorBase::deref() const {
2329 return current_->second;
2330 }
2331
2332 void ValueIteratorBase::increment() {
2333 ++current_;
2334 }
2335
2336 void ValueIteratorBase::decrement() {
2337 --current_;
2338 }
2339
2340 ValueIteratorBase::difference_type
2341 ValueIteratorBase::computeDistance(const SelfType& other) const {
2342 #ifdef JSON_USE_CPPTL_SMALLMAP
2343 return other.current_ - current_;
2344 #else
2345
2346
2347
2348
2349
2350 if (isNull_ && other.isNull_) {
2351 return 0;
2352 }
2353
2354
2355
2356
2357
2358
2359 difference_type myDistance = 0;
2360 for (Value::ObjectValues::iterator it = current_; it != other.current_;
2361 ++it) {
2362 ++myDistance;
2363 }
2364 return myDistance;
2365 #endif
2366 }
2367
2368 bool ValueIteratorBase::isEqual(const SelfType& other) const {
2369 if (isNull_) {
2370 return other.isNull_;
2371 }
2372 return current_ == other.current_;
2373 }
2374
2375 void ValueIteratorBase::copy(const SelfType& other) {
2376 current_ = other.current_;
2377 isNull_ = other.isNull_;
2378 }
2379
2380 Value ValueIteratorBase::key() const {
2381 const Value::CZString czstring = (*current_).first;
2382 if (czstring.data()) {
2383 if (czstring.isStaticString())
2384 return Value(StaticString(czstring.data()));
2385 return Value(czstring.data(), czstring.data() + czstring.length());
2386 }
2387 return Value(czstring.index());
2388 }
2389
2390 UInt ValueIteratorBase::index() const {
2391 const Value::CZString czstring = (*current_).first;
2392 if (!czstring.data())
2393 return czstring.index();
2394 return Value::UInt(-1);
2395 }
2396
2397 JSONCPP_STRING ValueIteratorBase::name() const {
2398 char const* keey;
2399 char const* end;
2400 keey = memberName(&end);
2401 if (!keey) return JSONCPP_STRING();
2402 return JSONCPP_STRING(keey, end);
2403 }
2404
2405 char const* ValueIteratorBase::memberName() const {
2406 const char* cname = (*current_).first.data();
2407 return cname ? cname : "";
2408 }
2409
2410 char const* ValueIteratorBase::memberName(char const** end) const {
2411 const char* cname = (*current_).first.data();
2412 if (!cname) {
2413 *end = NULL;
2414 return NULL;
2415 }
2416 *end = cname + (*current_).first.length();
2417 return cname;
2418 }
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428 ValueConstIterator::ValueConstIterator() {}
2429
2430 ValueConstIterator::ValueConstIterator(
2431 const Value::ObjectValues::iterator& current)
2432 : ValueIteratorBase(current) {}
2433
2434 ValueConstIterator::ValueConstIterator(ValueIterator const& other)
2435 : ValueIteratorBase(other) {}
2436
2437 ValueConstIterator& ValueConstIterator::
2438 operator=(const ValueIteratorBase& other) {
2439 copy(other);
2440 return *this;
2441 }
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451 ValueIterator::ValueIterator() {}
2452
2453 ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
2454 : ValueIteratorBase(current) {}
2455
2456 ValueIterator::ValueIterator(const ValueConstIterator& other)
2457 : ValueIteratorBase(other) {
2458 throwRuntimeError("ConstIterator to Iterator should never be allowed.");
2459 }
2460
2461 ValueIterator::ValueIterator(const ValueIterator& other)
2462 : ValueIteratorBase(other) {}
2463
2464 ValueIterator& ValueIterator::operator=(const SelfType& other) {
2465 copy(other);
2466 return *this;
2467 }
2468
2469 }
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489 #if !defined(JSON_IS_AMALGAMATION)
2490 #include <json/assertions.h>
2491 #include <json/value.h>
2492 #include <json/writer.h>
2493 #endif
2494 #include <math.h>
2495 #include <sstream>
2496 #include <utility>
2497 #include <cstring>
2498 #include <cassert>
2499 #ifdef JSON_USE_CPPTL
2500 #include <cpptl/conststring.h>
2501 #endif
2502 #include <cstddef> // size_t
2503 #include <algorithm> // min()
2504
2505 #define JSON_ASSERT_UNREACHABLE assert(false)
2506
2507 namespace Json {
2508
2509
2510
2511
2512 #if defined(__ARMEL__)
2513 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
2514 #else
2515 #define ALIGNAS(byte_alignment)
2516 #endif
2517
2518
2519
2520
2521
2522
2523 Value const& Value::nullSingleton()
2524 {
2525 static Value const nullStatic;
2526 return nullStatic;
2527 }
2528
2529
2530
2531 Value const& Value::null = Value::nullSingleton();
2532 Value const& Value::nullRef = Value::nullSingleton();
2533
2534 const Int Value::minInt = Int(~(UInt(-1) / 2));
2535 const Int Value::maxInt = Int(UInt(-1) / 2);
2536 const UInt Value::maxUInt = UInt(-1);
2537 #if defined(JSON_HAS_INT64)
2538 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
2539 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
2540 const UInt64 Value::maxUInt64 = UInt64(-1);
2541
2542
2543
2544 static const double maxUInt64AsDouble = 18446744073709551615.0;
2545 #endif
2546 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
2547 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
2548 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
2549
2550 const UInt Value::defaultRealPrecision = 17;
2551
2552 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2553 template <typename T, typename U>
2554 static inline bool InRange(double d, T min, U max) {
2555
2556
2557
2558 return d >= min && d <= max;
2559 }
2560 #else
2561 static inline double integerToDouble(Json::UInt64 value) {
2562 return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
2563 }
2564
2565 template <typename T> static inline double integerToDouble(T value) {
2566 return static_cast<double>(value);
2567 }
2568
2569 template <typename T, typename U>
2570 static inline bool InRange(double d, T min, U max) {
2571 return d >= integerToDouble(min) && d <= integerToDouble(max);
2572 }
2573 #endif
2574
2575
2576
2577
2578
2579
2580
2581
2582 static inline char* duplicateStringValue(const char* value,
2583 size_t length)
2584 {
2585
2586
2587 if (length >= static_cast<size_t>(Value::maxInt))
2588 length = Value::maxInt - 1;
2589
2590 char* newString = static_cast<char*>(malloc(length + 1));
2591 if (newString == NULL) {
2592 throwRuntimeError(
2593 "in Json::Value::duplicateStringValue(): "
2594 "Failed to allocate string value buffer");
2595 }
2596 memcpy(newString, value, length);
2597 newString[length] = 0;
2598 return newString;
2599 }
2600
2601
2602
2603 static inline char* duplicateAndPrefixStringValue(
2604 const char* value,
2605 unsigned int length)
2606 {
2607
2608
2609 JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
2610 "in Json::Value::duplicateAndPrefixStringValue(): "
2611 "length too big for prefixing");
2612 unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
2613 char* newString = static_cast<char*>(malloc(actualLength));
2614 if (newString == 0) {
2615 throwRuntimeError(
2616 "in Json::Value::duplicateAndPrefixStringValue(): "
2617 "Failed to allocate string value buffer");
2618 }
2619 *reinterpret_cast<unsigned*>(newString) = length;
2620 memcpy(newString + sizeof(unsigned), value, length);
2621 newString[actualLength - 1U] = 0;
2622 return newString;
2623 }
2624 inline static void decodePrefixedString(
2625 bool isPrefixed, char const* prefixed,
2626 unsigned* length, char const** value)
2627 {
2628 if (!isPrefixed) {
2629 *length = static_cast<unsigned>(strlen(prefixed));
2630 *value = prefixed;
2631 } else {
2632 *length = *reinterpret_cast<unsigned const*>(prefixed);
2633 *value = prefixed + sizeof(unsigned);
2634 }
2635 }
2636
2637
2638 #if JSONCPP_USING_SECURE_MEMORY
2639 static inline void releasePrefixedStringValue(char* value) {
2640 unsigned length = 0;
2641 char const* valueDecoded;
2642 decodePrefixedString(true, value, &length, &valueDecoded);
2643 size_t const size = sizeof(unsigned) + length + 1U;
2644 memset(value, 0, size);
2645 free(value);
2646 }
2647 static inline void releaseStringValue(char* value, unsigned length) {
2648
2649 size_t size = (length==0) ? strlen(value) : length;
2650 memset(value, 0, size);
2651 free(value);
2652 }
2653 #else
2654 static inline void releasePrefixedStringValue(char* value) {
2655 free(value);
2656 }
2657 static inline void releaseStringValue(char* value, unsigned) {
2658 free(value);
2659 }
2660 #endif
2661
2662 }
2663
2664
2665
2666
2667
2668
2669
2670
2671 #if !defined(JSON_IS_AMALGAMATION)
2672
2673 #include "json_valueiterator.inl"
2674 #endif
2675
2676 namespace Json {
2677
2678 Exception::Exception(JSONCPP_STRING const& msg)
2679 : msg_(msg)
2680 {}
2681 Exception::~Exception() JSONCPP_NOEXCEPT
2682 {}
2683 char const* Exception::what() const JSONCPP_NOEXCEPT
2684 {
2685 return msg_.c_str();
2686 }
2687 RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
2688 : Exception(msg)
2689 {}
2690 LogicError::LogicError(JSONCPP_STRING const& msg)
2691 : Exception(msg)
2692 {}
2693 JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
2694 {
2695 throw RuntimeError(msg);
2696 }
2697 JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
2698 {
2699 throw LogicError(msg);
2700 }
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710 Value::CommentInfo::CommentInfo() : comment_(0)
2711 {}
2712
2713 Value::CommentInfo::~CommentInfo() {
2714 if (comment_)
2715 releaseStringValue(comment_, 0u);
2716 }
2717
2718 void Value::CommentInfo::setComment(const char* text, size_t len) {
2719 if (comment_) {
2720 releaseStringValue(comment_, 0u);
2721 comment_ = 0;
2722 }
2723 JSON_ASSERT(text != 0);
2724 JSON_ASSERT_MESSAGE(
2725 text[0] == '\0' || text[0] == '/',
2726 "in Json::Value::setComment(): Comments must start with /");
2727
2728 comment_ = duplicateStringValue(text, len);
2729 }
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
2743
2744 Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
2745 : cstr_(str) {
2746
2747 storage_.policy_ = allocate & 0x3;
2748 storage_.length_ = ulength & 0x3FFFFFFF;
2749 }
2750
2751 Value::CZString::CZString(const CZString& other) {
2752 cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
2753 ? duplicateStringValue(other.cstr_, other.storage_.length_)
2754 : other.cstr_);
2755 storage_.policy_ = static_cast<unsigned>(other.cstr_
2756 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
2757 ? noDuplication : duplicate)
2758 : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
2759 storage_.length_ = other.storage_.length_;
2760 }
2761
2762 #if JSON_HAS_RVALUE_REFERENCES
2763 Value::CZString::CZString(CZString&& other)
2764 : cstr_(other.cstr_), index_(other.index_) {
2765 other.cstr_ = nullptr;
2766 }
2767 #endif
2768
2769 Value::CZString::~CZString() {
2770 if (cstr_ && storage_.policy_ == duplicate) {
2771 releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u);
2772 }
2773 }
2774
2775 void Value::CZString::swap(CZString& other) {
2776 std::swap(cstr_, other.cstr_);
2777 std::swap(index_, other.index_);
2778 }
2779
2780 Value::CZString& Value::CZString::operator=(const CZString& other) {
2781 cstr_ = other.cstr_;
2782 index_ = other.index_;
2783 return *this;
2784 }
2785
2786 #if JSON_HAS_RVALUE_REFERENCES
2787 Value::CZString& Value::CZString::operator=(CZString&& other) {
2788 cstr_ = other.cstr_;
2789 index_ = other.index_;
2790 other.cstr_ = nullptr;
2791 return *this;
2792 }
2793 #endif
2794
2795 bool Value::CZString::operator<(const CZString& other) const {
2796 if (!cstr_) return index_ < other.index_;
2797
2798
2799 unsigned this_len = this->storage_.length_;
2800 unsigned other_len = other.storage_.length_;
2801 unsigned min_len = std::min<unsigned>(this_len, other_len);
2802 JSON_ASSERT(this->cstr_ && other.cstr_);
2803 int comp = memcmp(this->cstr_, other.cstr_, min_len);
2804 if (comp < 0) return true;
2805 if (comp > 0) return false;
2806 return (this_len < other_len);
2807 }
2808
2809 bool Value::CZString::operator==(const CZString& other) const {
2810 if (!cstr_) return index_ == other.index_;
2811
2812
2813 unsigned this_len = this->storage_.length_;
2814 unsigned other_len = other.storage_.length_;
2815 if (this_len != other_len) return false;
2816 JSON_ASSERT(this->cstr_ && other.cstr_);
2817 int comp = memcmp(this->cstr_, other.cstr_, this_len);
2818 return comp == 0;
2819 }
2820
2821 ArrayIndex Value::CZString::index() const { return index_; }
2822
2823
2824 const char* Value::CZString::data() const { return cstr_; }
2825 unsigned Value::CZString::length() const { return storage_.length_; }
2826 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
2827
2828
2829
2830
2831
2832
2833
2834
2835
2836
2837
2838
2839
2840 Value::Value(ValueType vtype) {
2841 static char const emptyString[] = "";
2842 initBasic(vtype);
2843 switch (vtype) {
2844 case nullValue:
2845 break;
2846 case intValue:
2847 case uintValue:
2848 value_.int_ = 0;
2849 break;
2850 case realValue:
2851 value_.real_ = 0.0;
2852 break;
2853 case stringValue:
2854
2855 value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
2856 break;
2857 case arrayValue:
2858 case objectValue:
2859 value_.map_ = new ObjectValues();
2860 break;
2861 case booleanValue:
2862 value_.bool_ = false;
2863 break;
2864 default:
2865 JSON_ASSERT_UNREACHABLE;
2866 }
2867 }
2868
2869 Value::Value(Int value) {
2870 initBasic(intValue);
2871 value_.int_ = value;
2872 }
2873
2874 Value::Value(UInt value) {
2875 initBasic(uintValue);
2876 value_.uint_ = value;
2877 }
2878 #if defined(JSON_HAS_INT64)
2879 Value::Value(Int64 value) {
2880 initBasic(intValue);
2881 value_.int_ = value;
2882 }
2883 Value::Value(UInt64 value) {
2884 initBasic(uintValue);
2885 value_.uint_ = value;
2886 }
2887 #endif
2888
2889 Value::Value(double value) {
2890 initBasic(realValue);
2891 value_.real_ = value;
2892 }
2893
2894 Value::Value(const char* value) {
2895 initBasic(stringValue, true);
2896 JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
2897 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
2898 }
2899
2900 Value::Value(const char* beginValue, const char* endValue) {
2901 initBasic(stringValue, true);
2902 value_.string_ =
2903 duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
2904 }
2905
2906 Value::Value(const JSONCPP_STRING& value) {
2907 initBasic(stringValue, true);
2908 value_.string_ =
2909 duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
2910 }
2911
2912 Value::Value(const StaticString& value) {
2913 initBasic(stringValue);
2914 value_.string_ = const_cast<char*>(value.c_str());
2915 }
2916
2917 #ifdef JSON_USE_CPPTL
2918 Value::Value(const CppTL::ConstString& value) {
2919 initBasic(stringValue, true);
2920 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
2921 }
2922 #endif
2923
2924 Value::Value(bool value) {
2925 initBasic(booleanValue);
2926 value_.bool_ = value;
2927 }
2928
2929 Value::Value(const Value& other) {
2930 dupPayload(other);
2931 dupMeta(other);
2932 }
2933
2934 #if JSON_HAS_RVALUE_REFERENCES
2935
2936 Value::Value(Value&& other) {
2937 initBasic(nullValue);
2938 swap(other);
2939 }
2940 #endif
2941
2942 Value::~Value() {
2943 releasePayload();
2944
2945 delete[] comments_;
2946
2947 value_.uint_ = 0;
2948 }
2949
2950 Value& Value::operator=(Value other) {
2951 swap(other);
2952 return *this;
2953 }
2954
2955 void Value::swapPayload(Value& other) {
2956 ValueType temp = type_;
2957 type_ = other.type_;
2958 other.type_ = temp;
2959 std::swap(value_, other.value_);
2960 int temp2 = allocated_;
2961 allocated_ = other.allocated_;
2962 other.allocated_ = temp2 & 0x1;
2963 }
2964
2965 void Value::copyPayload(const Value& other) {
2966 releasePayload();
2967 dupPayload(other);
2968 }
2969
2970 void Value::swap(Value& other) {
2971 swapPayload(other);
2972 std::swap(comments_, other.comments_);
2973 std::swap(start_, other.start_);
2974 std::swap(limit_, other.limit_);
2975 }
2976
2977 void Value::copy(const Value& other) {
2978 copyPayload(other);
2979 delete[] comments_;
2980 dupMeta(other);
2981 }
2982
2983 ValueType Value::type() const { return type_; }
2984
2985 int Value::compare(const Value& other) const {
2986 if (*this < other)
2987 return -1;
2988 if (*this > other)
2989 return 1;
2990 return 0;
2991 }
2992
2993 bool Value::operator<(const Value& other) const {
2994 int typeDelta = type_ - other.type_;
2995 if (typeDelta)
2996 return typeDelta < 0 ? true : false;
2997 switch (type_) {
2998 case nullValue:
2999 return false;
3000 case intValue:
3001 return value_.int_ < other.value_.int_;
3002 case uintValue:
3003 return value_.uint_ < other.value_.uint_;
3004 case realValue:
3005 return value_.real_ < other.value_.real_;
3006 case booleanValue:
3007 return value_.bool_ < other.value_.bool_;
3008 case stringValue:
3009 {
3010 if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
3011 if (other.value_.string_) return true;
3012 else return false;
3013 }
3014 unsigned this_len;
3015 unsigned other_len;
3016 char const* this_str;
3017 char const* other_str;
3018 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3019 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3020 unsigned min_len = std::min<unsigned>(this_len, other_len);
3021 JSON_ASSERT(this_str && other_str);
3022 int comp = memcmp(this_str, other_str, min_len);
3023 if (comp < 0) return true;
3024 if (comp > 0) return false;
3025 return (this_len < other_len);
3026 }
3027 case arrayValue:
3028 case objectValue: {
3029 int delta = int(value_.map_->size() - other.value_.map_->size());
3030 if (delta)
3031 return delta < 0;
3032 return (*value_.map_) < (*other.value_.map_);
3033 }
3034 default:
3035 JSON_ASSERT_UNREACHABLE;
3036 }
3037 return false;
3038 }
3039
3040 bool Value::operator<=(const Value& other) const { return !(other < *this); }
3041
3042 bool Value::operator>=(const Value& other) const { return !(*this < other); }
3043
3044 bool Value::operator>(const Value& other) const { return other < *this; }
3045
3046 bool Value::operator==(const Value& other) const {
3047
3048
3049
3050
3051 int temp = other.type_;
3052 if (type_ != temp)
3053 return false;
3054 switch (type_) {
3055 case nullValue:
3056 return true;
3057 case intValue:
3058 return value_.int_ == other.value_.int_;
3059 case uintValue:
3060 return value_.uint_ == other.value_.uint_;
3061 case realValue:
3062 return value_.real_ == other.value_.real_;
3063 case booleanValue:
3064 return value_.bool_ == other.value_.bool_;
3065 case stringValue:
3066 {
3067 if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
3068 return (value_.string_ == other.value_.string_);
3069 }
3070 unsigned this_len;
3071 unsigned other_len;
3072 char const* this_str;
3073 char const* other_str;
3074 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3075 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3076 if (this_len != other_len) return false;
3077 JSON_ASSERT(this_str && other_str);
3078 int comp = memcmp(this_str, other_str, this_len);
3079 return comp == 0;
3080 }
3081 case arrayValue:
3082 case objectValue:
3083 return value_.map_->size() == other.value_.map_->size() &&
3084 (*value_.map_) == (*other.value_.map_);
3085 default:
3086 JSON_ASSERT_UNREACHABLE;
3087 }
3088 return false;
3089 }
3090
3091 bool Value::operator!=(const Value& other) const { return !(*this == other); }
3092
3093 const char* Value::asCString() const {
3094 JSON_ASSERT_MESSAGE(type_ == stringValue,
3095 "in Json::Value::asCString(): requires stringValue");
3096 if (value_.string_ == 0) return 0;
3097 unsigned this_len;
3098 char const* this_str;
3099 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3100 return this_str;
3101 }
3102
3103 #if JSONCPP_USING_SECURE_MEMORY
3104 unsigned Value::getCStringLength() const {
3105 JSON_ASSERT_MESSAGE(type_ == stringValue,
3106 "in Json::Value::asCString(): requires stringValue");
3107 if (value_.string_ == 0) return 0;
3108 unsigned this_len;
3109 char const* this_str;
3110 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3111 return this_len;
3112 }
3113 #endif
3114
3115 bool Value::getString(char const** str, char const** cend) const {
3116 if (type_ != stringValue) return false;
3117 if (value_.string_ == 0) return false;
3118 unsigned length;
3119 decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
3120 *cend = *str + length;
3121 return true;
3122 }
3123
3124 JSONCPP_STRING Value::asString() const {
3125 switch (type_) {
3126 case nullValue:
3127 return "";
3128 case stringValue:
3129 {
3130 if (value_.string_ == 0) return "";
3131 unsigned this_len;
3132 char const* this_str;
3133 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3134 return JSONCPP_STRING(this_str, this_len);
3135 }
3136 case booleanValue:
3137 return value_.bool_ ? "true" : "false";
3138 case intValue:
3139 return valueToString(value_.int_);
3140 case uintValue:
3141 return valueToString(value_.uint_);
3142 case realValue:
3143 return valueToString(value_.real_);
3144 default:
3145 JSON_FAIL_MESSAGE("Type is not convertible to string");
3146 }
3147 }
3148
3149 #ifdef JSON_USE_CPPTL
3150 CppTL::ConstString Value::asConstString() const {
3151 unsigned len;
3152 char const* str;
3153 decodePrefixedString(allocated_, value_.string_,
3154 &len, &str);
3155 return CppTL::ConstString(str, len);
3156 }
3157 #endif
3158
3159 Value::Int Value::asInt() const {
3160 switch (type_) {
3161 case intValue:
3162 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
3163 return Int(value_.int_);
3164 case uintValue:
3165 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
3166 return Int(value_.uint_);
3167 case realValue:
3168 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
3169 "double out of Int range");
3170 return Int(value_.real_);
3171 case nullValue:
3172 return 0;
3173 case booleanValue:
3174 return value_.bool_ ? 1 : 0;
3175 default:
3176 break;
3177 }
3178 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
3179 }
3180
3181 Value::UInt Value::asUInt() const {
3182 switch (type_) {
3183 case intValue:
3184 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
3185 return UInt(value_.int_);
3186 case uintValue:
3187 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
3188 return UInt(value_.uint_);
3189 case realValue:
3190 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
3191 "double out of UInt range");
3192 return UInt(value_.real_);
3193 case nullValue:
3194 return 0;
3195 case booleanValue:
3196 return value_.bool_ ? 1 : 0;
3197 default:
3198 break;
3199 }
3200 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
3201 }
3202
3203 #if defined(JSON_HAS_INT64)
3204
3205 Value::Int64 Value::asInt64() const {
3206 switch (type_) {
3207 case intValue:
3208 return Int64(value_.int_);
3209 case uintValue:
3210 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
3211 return Int64(value_.uint_);
3212 case realValue:
3213 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
3214 "double out of Int64 range");
3215 return Int64(value_.real_);
3216 case nullValue:
3217 return 0;
3218 case booleanValue:
3219 return value_.bool_ ? 1 : 0;
3220 default:
3221 break;
3222 }
3223 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
3224 }
3225
3226 Value::UInt64 Value::asUInt64() const {
3227 switch (type_) {
3228 case intValue:
3229 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
3230 return UInt64(value_.int_);
3231 case uintValue:
3232 return UInt64(value_.uint_);
3233 case realValue:
3234 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
3235 "double out of UInt64 range");
3236 return UInt64(value_.real_);
3237 case nullValue:
3238 return 0;
3239 case booleanValue:
3240 return value_.bool_ ? 1 : 0;
3241 default:
3242 break;
3243 }
3244 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
3245 }
3246 #endif
3247
3248 LargestInt Value::asLargestInt() const {
3249 #if defined(JSON_NO_INT64)
3250 return asInt();
3251 #else
3252 return asInt64();
3253 #endif
3254 }
3255
3256 LargestUInt Value::asLargestUInt() const {
3257 #if defined(JSON_NO_INT64)
3258 return asUInt();
3259 #else
3260 return asUInt64();
3261 #endif
3262 }
3263
3264 double Value::asDouble() const {
3265 switch (type_) {
3266 case intValue:
3267 return static_cast<double>(value_.int_);
3268 case uintValue:
3269 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3270 return static_cast<double>(value_.uint_);
3271 #else
3272 return integerToDouble(value_.uint_);
3273 #endif
3274 case realValue:
3275 return value_.real_;
3276 case nullValue:
3277 return 0.0;
3278 case booleanValue:
3279 return value_.bool_ ? 1.0 : 0.0;
3280 default:
3281 break;
3282 }
3283 JSON_FAIL_MESSAGE("Value is not convertible to double.");
3284 }
3285
3286 float Value::asFloat() const {
3287 switch (type_) {
3288 case intValue:
3289 return static_cast<float>(value_.int_);
3290 case uintValue:
3291 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3292 return static_cast<float>(value_.uint_);
3293 #else
3294
3295 return static_cast<float>(integerToDouble(value_.uint_));
3296 #endif
3297 case realValue:
3298 return static_cast<float>(value_.real_);
3299 case nullValue:
3300 return 0.0;
3301 case booleanValue:
3302 return value_.bool_ ? 1.0f : 0.0f;
3303 default:
3304 break;
3305 }
3306 JSON_FAIL_MESSAGE("Value is not convertible to float.");
3307 }
3308
3309 bool Value::asBool() const {
3310 switch (type_) {
3311 case booleanValue:
3312 return value_.bool_;
3313 case nullValue:
3314 return false;
3315 case intValue:
3316 return value_.int_ ? true : false;
3317 case uintValue:
3318 return value_.uint_ ? true : false;
3319 case realValue:
3320
3321 return (value_.real_ != 0.0) ? true : false;
3322 default:
3323 break;
3324 }
3325 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
3326 }
3327
3328 bool Value::isConvertibleTo(ValueType other) const {
3329 switch (other) {
3330 case nullValue:
3331 return (isNumeric() && asDouble() == 0.0) ||
3332 (type_ == booleanValue && value_.bool_ == false) ||
3333 (type_ == stringValue && asString().empty()) ||
3334 (type_ == arrayValue && value_.map_->size() == 0) ||
3335 (type_ == objectValue && value_.map_->size() == 0) ||
3336 type_ == nullValue;
3337 case intValue:
3338 return isInt() ||
3339 (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
3340 type_ == booleanValue || type_ == nullValue;
3341 case uintValue:
3342 return isUInt() ||
3343 (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
3344 type_ == booleanValue || type_ == nullValue;
3345 case realValue:
3346 return isNumeric() || type_ == booleanValue || type_ == nullValue;
3347 case booleanValue:
3348 return isNumeric() || type_ == booleanValue || type_ == nullValue;
3349 case stringValue:
3350 return isNumeric() || type_ == booleanValue || type_ == stringValue ||
3351 type_ == nullValue;
3352 case arrayValue:
3353 return type_ == arrayValue || type_ == nullValue;
3354 case objectValue:
3355 return type_ == objectValue || type_ == nullValue;
3356 }
3357 JSON_ASSERT_UNREACHABLE;
3358 return false;
3359 }
3360
3361
3362 ArrayIndex Value::size() const {
3363 switch (type_) {
3364 case nullValue:
3365 case intValue:
3366 case uintValue:
3367 case realValue:
3368 case booleanValue:
3369 case stringValue:
3370 return 0;
3371 case arrayValue:
3372 if (!value_.map_->empty()) {
3373 ObjectValues::const_iterator itLast = value_.map_->end();
3374 --itLast;
3375 return (*itLast).first.index() + 1;
3376 }
3377 return 0;
3378 case objectValue:
3379 return ArrayIndex(value_.map_->size());
3380 }
3381 JSON_ASSERT_UNREACHABLE;
3382 return 0;
3383 }
3384
3385 bool Value::empty() const {
3386 if (isNull() || isArray() || isObject())
3387 return size() == 0u;
3388 else
3389 return false;
3390 }
3391
3392 Value::operator bool() const { return ! isNull(); }
3393
3394 void Value::clear() {
3395 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
3396 type_ == objectValue,
3397 "in Json::Value::clear(): requires complex value");
3398 start_ = 0;
3399 limit_ = 0;
3400 switch (type_) {
3401 case arrayValue:
3402 case objectValue:
3403 value_.map_->clear();
3404 break;
3405 default:
3406 break;
3407 }
3408 }
3409
3410 void Value::resize(ArrayIndex newSize) {
3411 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3412 "in Json::Value::resize(): requires arrayValue");
3413 if (type_ == nullValue)
3414 *this = Value(arrayValue);
3415 ArrayIndex oldSize = size();
3416 if (newSize == 0)
3417 clear();
3418 else if (newSize > oldSize)
3419 this->operator[](newSize - 1);
3420 else {
3421 for (ArrayIndex index = newSize; index < oldSize; ++index) {
3422 value_.map_->erase(index);
3423 }
3424 JSON_ASSERT(size() == newSize);
3425 }
3426 }
3427
3428 Value& Value::operator[](ArrayIndex index) {
3429 JSON_ASSERT_MESSAGE(
3430 type_ == nullValue || type_ == arrayValue,
3431 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
3432 if (type_ == nullValue)
3433 *this = Value(arrayValue);
3434 CZString key(index);
3435 ObjectValues::iterator it = value_.map_->lower_bound(key);
3436 if (it != value_.map_->end() && (*it).first == key)
3437 return (*it).second;
3438
3439 ObjectValues::value_type defaultValue(key, nullSingleton());
3440 it = value_.map_->insert(it, defaultValue);
3441 return (*it).second;
3442 }
3443
3444 Value& Value::operator[](int index) {
3445 JSON_ASSERT_MESSAGE(
3446 index >= 0,
3447 "in Json::Value::operator[](int index): index cannot be negative");
3448 return (*this)[ArrayIndex(index)];
3449 }
3450
3451 const Value& Value::operator[](ArrayIndex index) const {
3452 JSON_ASSERT_MESSAGE(
3453 type_ == nullValue || type_ == arrayValue,
3454 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
3455 if (type_ == nullValue)
3456 return nullSingleton();
3457 CZString key(index);
3458 ObjectValues::const_iterator it = value_.map_->find(key);
3459 if (it == value_.map_->end())
3460 return nullSingleton();
3461 return (*it).second;
3462 }
3463
3464 const Value& Value::operator[](int index) const {
3465 JSON_ASSERT_MESSAGE(
3466 index >= 0,
3467 "in Json::Value::operator[](int index) const: index cannot be negative");
3468 return (*this)[ArrayIndex(index)];
3469 }
3470
3471 void Value::initBasic(ValueType vtype, bool allocated) {
3472 type_ = vtype;
3473 allocated_ = allocated;
3474 comments_ = 0;
3475 start_ = 0;
3476 limit_ = 0;
3477 }
3478
3479 void Value::dupPayload(const Value& other) {
3480 type_ = other.type_;
3481 allocated_ = false;
3482 switch (type_) {
3483 case nullValue:
3484 case intValue:
3485 case uintValue:
3486 case realValue:
3487 case booleanValue:
3488 value_ = other.value_;
3489 break;
3490 case stringValue:
3491 if (other.value_.string_ && other.allocated_) {
3492 unsigned len;
3493 char const* str;
3494 decodePrefixedString(other.allocated_, other.value_.string_,
3495 &len, &str);
3496 value_.string_ = duplicateAndPrefixStringValue(str, len);
3497 allocated_ = true;
3498 } else {
3499 value_.string_ = other.value_.string_;
3500 }
3501 break;
3502 case arrayValue:
3503 case objectValue:
3504 value_.map_ = new ObjectValues(*other.value_.map_);
3505 break;
3506 default:
3507 JSON_ASSERT_UNREACHABLE;
3508 }
3509 }
3510
3511 void Value::releasePayload() {
3512 switch (type_) {
3513 case nullValue:
3514 case intValue:
3515 case uintValue:
3516 case realValue:
3517 case booleanValue:
3518 break;
3519 case stringValue:
3520 if (allocated_)
3521 releasePrefixedStringValue(value_.string_);
3522 break;
3523 case arrayValue:
3524 case objectValue:
3525 delete value_.map_;
3526 break;
3527 default:
3528 JSON_ASSERT_UNREACHABLE;
3529 }
3530 }
3531
3532 void Value::dupMeta(const Value& other) {
3533 if (other.comments_) {
3534 comments_ = new CommentInfo[numberOfCommentPlacement];
3535 for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
3536 const CommentInfo& otherComment = other.comments_[comment];
3537 if (otherComment.comment_)
3538 comments_[comment].setComment(
3539 otherComment.comment_, strlen(otherComment.comment_));
3540 }
3541 } else {
3542 comments_ = 0;
3543 }
3544 start_ = other.start_;
3545 limit_ = other.limit_;
3546 }
3547
3548
3549
3550
3551 Value& Value::resolveReference(const char* key) {
3552 JSON_ASSERT_MESSAGE(
3553 type_ == nullValue || type_ == objectValue,
3554 "in Json::Value::resolveReference(): requires objectValue");
3555 if (type_ == nullValue)
3556 *this = Value(objectValue);
3557 CZString actualKey(
3558 key, static_cast<unsigned>(strlen(key)), CZString::noDuplication);
3559 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3560 if (it != value_.map_->end() && (*it).first == actualKey)
3561 return (*it).second;
3562
3563 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3564 it = value_.map_->insert(it, defaultValue);
3565 Value& value = (*it).second;
3566 return value;
3567 }
3568
3569
3570 Value& Value::resolveReference(char const* key, char const* cend)
3571 {
3572 JSON_ASSERT_MESSAGE(
3573 type_ == nullValue || type_ == objectValue,
3574 "in Json::Value::resolveReference(key, end): requires objectValue");
3575 if (type_ == nullValue)
3576 *this = Value(objectValue);
3577 CZString actualKey(
3578 key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
3579 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3580 if (it != value_.map_->end() && (*it).first == actualKey)
3581 return (*it).second;
3582
3583 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3584 it = value_.map_->insert(it, defaultValue);
3585 Value& value = (*it).second;
3586 return value;
3587 }
3588
3589 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
3590 const Value* value = &((*this)[index]);
3591 return value == &nullSingleton() ? defaultValue : *value;
3592 }
3593
3594 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
3595
3596 Value const* Value::find(char const* key, char const* cend) const
3597 {
3598 JSON_ASSERT_MESSAGE(
3599 type_ == nullValue || type_ == objectValue,
3600 "in Json::Value::find(key, end, found): requires objectValue or nullValue");
3601 if (type_ == nullValue) return NULL;
3602 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3603 ObjectValues::const_iterator it = value_.map_->find(actualKey);
3604 if (it == value_.map_->end()) return NULL;
3605 return &(*it).second;
3606 }
3607 const Value& Value::operator[](const char* key) const
3608 {
3609 Value const* found = find(key, key + strlen(key));
3610 if (!found) return nullSingleton();
3611 return *found;
3612 }
3613 Value const& Value::operator[](JSONCPP_STRING const& key) const
3614 {
3615 Value const* found = find(key.data(), key.data() + key.length());
3616 if (!found) return nullSingleton();
3617 return *found;
3618 }
3619
3620 Value& Value::operator[](const char* key) {
3621 return resolveReference(key, key + strlen(key));
3622 }
3623
3624 Value& Value::operator[](const JSONCPP_STRING& key) {
3625 return resolveReference(key.data(), key.data() + key.length());
3626 }
3627
3628 Value& Value::operator[](const StaticString& key) {
3629 return resolveReference(key.c_str());
3630 }
3631
3632 #ifdef JSON_USE_CPPTL
3633 Value& Value::operator[](const CppTL::ConstString& key) {
3634 return resolveReference(key.c_str(), key.end_c_str());
3635 }
3636 Value const& Value::operator[](CppTL::ConstString const& key) const
3637 {
3638 Value const* found = find(key.c_str(), key.end_c_str());
3639 if (!found) return nullSingleton();
3640 return *found;
3641 }
3642 #endif
3643
3644 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
3645
3646 #if JSON_HAS_RVALUE_REFERENCES
3647 Value& Value::append(Value&& value) { return (*this)[size()] = std::move(value); }
3648 #endif
3649
3650 Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
3651 {
3652 Value const* found = find(key, cend);
3653 return !found ? defaultValue : *found;
3654 }
3655 Value Value::get(char const* key, Value const& defaultValue) const
3656 {
3657 return get(key, key + strlen(key), defaultValue);
3658 }
3659 Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
3660 {
3661 return get(key.data(), key.data() + key.length(), defaultValue);
3662 }
3663
3664
3665 bool Value::removeMember(const char* key, const char* cend, Value* removed)
3666 {
3667 if (type_ != objectValue) {
3668 return false;
3669 }
3670 CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3671 ObjectValues::iterator it = value_.map_->find(actualKey);
3672 if (it == value_.map_->end())
3673 return false;
3674 if (removed)
3675 #if JSON_HAS_RVALUE_REFERENCES
3676 *removed = std::move(it->second);
3677 #else
3678 *removed = it->second;
3679 #endif
3680 value_.map_->erase(it);
3681 return true;
3682 }
3683 bool Value::removeMember(const char* key, Value* removed)
3684 {
3685 return removeMember(key, key + strlen(key), removed);
3686 }
3687 bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
3688 {
3689 return removeMember(key.data(), key.data() + key.length(), removed);
3690 }
3691 void Value::removeMember(const char* key)
3692 {
3693 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3694 "in Json::Value::removeMember(): requires objectValue");
3695 if (type_ == nullValue)
3696 return;
3697
3698 CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
3699 value_.map_->erase(actualKey);
3700 }
3701 void Value::removeMember(const JSONCPP_STRING& key)
3702 {
3703 removeMember(key.c_str());
3704 }
3705
3706 bool Value::removeIndex(ArrayIndex index, Value* removed) {
3707 if (type_ != arrayValue) {
3708 return false;
3709 }
3710 CZString key(index);
3711 ObjectValues::iterator it = value_.map_->find(key);
3712 if (it == value_.map_->end()) {
3713 return false;
3714 }
3715 *removed = it->second;
3716 ArrayIndex oldSize = size();
3717
3718 for (ArrayIndex i = index; i < (oldSize - 1); ++i){
3719 CZString keey(i);
3720 (*value_.map_)[keey] = (*this)[i + 1];
3721 }
3722
3723 CZString keyLast(oldSize - 1);
3724 ObjectValues::iterator itLast = value_.map_->find(keyLast);
3725 value_.map_->erase(itLast);
3726 return true;
3727 }
3728
3729 #ifdef JSON_USE_CPPTL
3730 Value Value::get(const CppTL::ConstString& key,
3731 const Value& defaultValue) const {
3732 return get(key.c_str(), key.end_c_str(), defaultValue);
3733 }
3734 #endif
3735
3736 bool Value::isMember(char const* key, char const* cend) const
3737 {
3738 Value const* value = find(key, cend);
3739 return NULL != value;
3740 }
3741 bool Value::isMember(char const* key) const
3742 {
3743 return isMember(key, key + strlen(key));
3744 }
3745 bool Value::isMember(JSONCPP_STRING const& key) const
3746 {
3747 return isMember(key.data(), key.data() + key.length());
3748 }
3749
3750 #ifdef JSON_USE_CPPTL
3751 bool Value::isMember(const CppTL::ConstString& key) const {
3752 return isMember(key.c_str(), key.end_c_str());
3753 }
3754 #endif
3755
3756 Value::Members Value::getMemberNames() const {
3757 JSON_ASSERT_MESSAGE(
3758 type_ == nullValue || type_ == objectValue,
3759 "in Json::Value::getMemberNames(), value must be objectValue");
3760 if (type_ == nullValue)
3761 return Value::Members();
3762 Members members;
3763 members.reserve(value_.map_->size());
3764 ObjectValues::const_iterator it = value_.map_->begin();
3765 ObjectValues::const_iterator itEnd = value_.map_->end();
3766 for (; it != itEnd; ++it) {
3767 members.push_back(JSONCPP_STRING((*it).first.data(),
3768 (*it).first.length()));
3769 }
3770 return members;
3771 }
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
3783
3784
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798 static bool IsIntegral(double d) {
3799 double integral_part;
3800 return modf(d, &integral_part) == 0.0;
3801 }
3802
3803 bool Value::isNull() const { return type_ == nullValue; }
3804
3805 bool Value::isBool() const { return type_ == booleanValue; }
3806
3807 bool Value::isInt() const {
3808 switch (type_) {
3809 case intValue:
3810 #if defined(JSON_HAS_INT64)
3811 return value_.int_ >= minInt && value_.int_ <= maxInt;
3812 #else
3813 return true;
3814 #endif
3815 case uintValue:
3816 return value_.uint_ <= UInt(maxInt);
3817 case realValue:
3818 return value_.real_ >= minInt && value_.real_ <= maxInt &&
3819 IsIntegral(value_.real_);
3820 default:
3821 break;
3822 }
3823 return false;
3824 }
3825
3826 bool Value::isUInt() const {
3827 switch (type_) {
3828 case intValue:
3829 #if defined(JSON_HAS_INT64)
3830 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
3831 #else
3832 return value_.int_ >= 0;
3833 #endif
3834 case uintValue:
3835 #if defined(JSON_HAS_INT64)
3836 return value_.uint_ <= maxUInt;
3837 #else
3838 return true;
3839 #endif
3840 case realValue:
3841 return value_.real_ >= 0 && value_.real_ <= maxUInt &&
3842 IsIntegral(value_.real_);
3843 default:
3844 break;
3845 }
3846 return false;
3847 }
3848
3849 bool Value::isInt64() const {
3850 #if defined(JSON_HAS_INT64)
3851 switch (type_) {
3852 case intValue:
3853 return true;
3854 case uintValue:
3855 return value_.uint_ <= UInt64(maxInt64);
3856 case realValue:
3857
3858
3859
3860 return value_.real_ >= double(minInt64) &&
3861 value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
3862 default:
3863 break;
3864 }
3865 #endif
3866 return false;
3867 }
3868
3869 bool Value::isUInt64() const {
3870 #if defined(JSON_HAS_INT64)
3871 switch (type_) {
3872 case intValue:
3873 return value_.int_ >= 0;
3874 case uintValue:
3875 return true;
3876 case realValue:
3877
3878
3879
3880 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
3881 IsIntegral(value_.real_);
3882 default:
3883 break;
3884 }
3885 #endif
3886 return false;
3887 }
3888
3889 bool Value::isIntegral() const {
3890 switch (type_) {
3891 case intValue:
3892 case uintValue:
3893 return true;
3894 case realValue:
3895 #if defined(JSON_HAS_INT64)
3896
3897
3898
3899 return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
3900 #else
3901 return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
3902 #endif
3903 default:
3904 break;
3905 }
3906 return false;
3907 }
3908
3909 bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
3910
3911 bool Value::isNumeric() const { return isDouble(); }
3912
3913 bool Value::isString() const { return type_ == stringValue; }
3914
3915 bool Value::isArray() const { return type_ == arrayValue; }
3916
3917 bool Value::isObject() const { return type_ == objectValue; }
3918
3919 void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
3920 if (!comments_)
3921 comments_ = new CommentInfo[numberOfCommentPlacement];
3922 if ((len > 0) && (comment[len-1] == '\n')) {
3923
3924 len -= 1;
3925 }
3926 comments_[placement].setComment(comment, len);
3927 }
3928
3929 void Value::setComment(const char* comment, CommentPlacement placement) {
3930 setComment(comment, strlen(comment), placement);
3931 }
3932
3933 void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
3934 setComment(comment.c_str(), comment.length(), placement);
3935 }
3936
3937 bool Value::hasComment(CommentPlacement placement) const {
3938 return comments_ != 0 && comments_[placement].comment_ != 0;
3939 }
3940
3941 JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
3942 if (hasComment(placement))
3943 return comments_[placement].comment_;
3944 return "";
3945 }
3946
3947 void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
3948
3949 void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
3950
3951 ptrdiff_t Value::getOffsetStart() const { return start_; }
3952
3953 ptrdiff_t Value::getOffsetLimit() const { return limit_; }
3954
3955 JSONCPP_STRING Value::toStyledString() const {
3956 StreamWriterBuilder builder;
3957
3958 JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
3959 out += Json::writeString(builder, *this);
3960 out += "\n";
3961
3962 return out;
3963 }
3964
3965 Value::const_iterator Value::begin() const {
3966 switch (type_) {
3967 case arrayValue:
3968 case objectValue:
3969 if (value_.map_)
3970 return const_iterator(value_.map_->begin());
3971 break;
3972 default:
3973 break;
3974 }
3975 return const_iterator();
3976 }
3977
3978 Value::const_iterator Value::end() const {
3979 switch (type_) {
3980 case arrayValue:
3981 case objectValue:
3982 if (value_.map_)
3983 return const_iterator(value_.map_->end());
3984 break;
3985 default:
3986 break;
3987 }
3988 return const_iterator();
3989 }
3990
3991 Value::iterator Value::begin() {
3992 switch (type_) {
3993 case arrayValue:
3994 case objectValue:
3995 if (value_.map_)
3996 return iterator(value_.map_->begin());
3997 break;
3998 default:
3999 break;
4000 }
4001 return iterator();
4002 }
4003
4004 Value::iterator Value::end() {
4005 switch (type_) {
4006 case arrayValue:
4007 case objectValue:
4008 if (value_.map_)
4009 return iterator(value_.map_->end());
4010 break;
4011 default:
4012 break;
4013 }
4014 return iterator();
4015 }
4016
4017
4018
4019
4020 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
4021
4022 PathArgument::PathArgument(ArrayIndex index)
4023 : key_(), index_(index), kind_(kindIndex) {}
4024
4025 PathArgument::PathArgument(const char* key)
4026 : key_(key), index_(), kind_(kindKey) {}
4027
4028 PathArgument::PathArgument(const JSONCPP_STRING& key)
4029 : key_(key.c_str()), index_(), kind_(kindKey) {}
4030
4031
4032
4033
4034 Path::Path(const JSONCPP_STRING& path,
4035 const PathArgument& a1,
4036 const PathArgument& a2,
4037 const PathArgument& a3,
4038 const PathArgument& a4,
4039 const PathArgument& a5) {
4040 InArgs in;
4041 in.reserve(5);
4042 in.push_back(&a1);
4043 in.push_back(&a2);
4044 in.push_back(&a3);
4045 in.push_back(&a4);
4046 in.push_back(&a5);
4047 makePath(path, in);
4048 }
4049
4050 void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
4051 const char* current = path.c_str();
4052 const char* end = current + path.length();
4053 InArgs::const_iterator itInArg = in.begin();
4054 while (current != end) {
4055 if (*current == '[') {
4056 ++current;
4057 if (*current == '%')
4058 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
4059 else {
4060 ArrayIndex index = 0;
4061 for (; current != end && *current >= '0' && *current <= '9'; ++current)
4062 index = index * 10 + ArrayIndex(*current - '0');
4063 args_.push_back(index);
4064 }
4065 if (current == end || *++current != ']')
4066 invalidPath(path, int(current - path.c_str()));
4067 } else if (*current == '%') {
4068 addPathInArg(path, in, itInArg, PathArgument::kindKey);
4069 ++current;
4070 } else if (*current == '.' || *current == ']') {
4071 ++current;
4072 } else {
4073 const char* beginName = current;
4074 while (current != end && !strchr("[.", *current))
4075 ++current;
4076 args_.push_back(JSONCPP_STRING(beginName, current));
4077 }
4078 }
4079 }
4080
4081 void Path::addPathInArg(const JSONCPP_STRING& ,
4082 const InArgs& in,
4083 InArgs::const_iterator& itInArg,
4084 PathArgument::Kind kind) {
4085 if (itInArg == in.end()) {
4086
4087 } else if ((*itInArg)->kind_ != kind) {
4088
4089 } else {
4090 args_.push_back(**itInArg++);
4091 }
4092 }
4093
4094 void Path::invalidPath(const JSONCPP_STRING& , int ) {
4095
4096 }
4097
4098 const Value& Path::resolve(const Value& root) const {
4099 const Value* node = &root;
4100 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4101 const PathArgument& arg = *it;
4102 if (arg.kind_ == PathArgument::kindIndex) {
4103 if (!node->isArray() || !node->isValidIndex(arg.index_)) {
4104
4105 return Value::null;
4106 }
4107 node = &((*node)[arg.index_]);
4108 } else if (arg.kind_ == PathArgument::kindKey) {
4109 if (!node->isObject()) {
4110
4111 return Value::null;
4112 }
4113 node = &((*node)[arg.key_]);
4114 if (node == &Value::nullSingleton()) {
4115
4116
4117 return Value::null;
4118 }
4119 }
4120 }
4121 return *node;
4122 }
4123
4124 Value Path::resolve(const Value& root, const Value& defaultValue) const {
4125 const Value* node = &root;
4126 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4127 const PathArgument& arg = *it;
4128 if (arg.kind_ == PathArgument::kindIndex) {
4129 if (!node->isArray() || !node->isValidIndex(arg.index_))
4130 return defaultValue;
4131 node = &((*node)[arg.index_]);
4132 } else if (arg.kind_ == PathArgument::kindKey) {
4133 if (!node->isObject())
4134 return defaultValue;
4135 node = &((*node)[arg.key_]);
4136 if (node == &Value::nullSingleton())
4137 return defaultValue;
4138 }
4139 }
4140 return *node;
4141 }
4142
4143 Value& Path::make(Value& root) const {
4144 Value* node = &root;
4145 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4146 const PathArgument& arg = *it;
4147 if (arg.kind_ == PathArgument::kindIndex) {
4148 if (!node->isArray()) {
4149
4150 }
4151 node = &((*node)[arg.index_]);
4152 } else if (arg.kind_ == PathArgument::kindKey) {
4153 if (!node->isObject()) {
4154
4155 }
4156 node = &((*node)[arg.key_]);
4157 }
4158 }
4159 return *node;
4160 }
4161
4162 }
4163
4164
4165
4166
4167
4168
4169
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182 #if !defined(JSON_IS_AMALGAMATION)
4183 #include <json/writer.h>
4184 #include "json_tool.h"
4185 #endif
4186 #include <iomanip>
4187 #include <memory>
4188 #include <sstream>
4189 #include <utility>
4190 #include <set>
4191 #include <cassert>
4192 #include <cstring>
4193 #include <cstdio>
4194
4195 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800
4196 #include <float.h>
4197 #define isfinite _finite
4198 #elif defined(__sun) && defined(__SVR4)
4199 #if !defined(isfinite)
4200 #include <ieeefp.h>
4201 #define isfinite finite
4202 #endif
4203 #elif defined(_AIX)
4204 #if !defined(isfinite)
4205 #include <math.h>
4206 #define isfinite finite
4207 #endif
4208 #elif defined(__hpux)
4209 #if !defined(isfinite)
4210 #if defined(__ia64) && !defined(finite)
4211 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \
4212 _Isfinitef(x) : _IsFinite(x)))
4213 #else
4214 #include <math.h>
4215 #define isfinite finite
4216 #endif
4217 #endif
4218 #else
4219 #include <cmath>
4220 #if !(defined(__QNXNTO__))
4221 #define isfinite std::isfinite
4222 #endif
4223 #endif
4224
4225 #if defined(_MSC_VER)
4226 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500
4227 #define snprintf sprintf_s
4228 #elif _MSC_VER >= 1900
4229 #define snprintf std::snprintf
4230 #else
4231 #define snprintf _snprintf
4232 #endif
4233 #elif defined(__ANDROID__) || defined(__QNXNTO__)
4234 #define snprintf snprintf
4235 #elif __cplusplus >= 201103L
4236 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
4237 #define snprintf std::snprintf
4238 #endif
4239 #endif
4240
4241 #if defined(__BORLANDC__)
4242 #include <float.h>
4243 #define isfinite _finite
4244 #define snprintf _snprintf
4245 #endif
4246
4247 #if defined(_MSC_VER) && _MSC_VER >= 1400
4248
4249 #pragma warning(disable : 4996)
4250 #endif
4251
4252 namespace Json {
4253
4254 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
4255 typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
4256 #else
4257 typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
4258 #endif
4259
4260 JSONCPP_STRING valueToString(LargestInt value) {
4261 UIntToStringBuffer buffer;
4262 char* current = buffer + sizeof(buffer);
4263 if (value == Value::minLargestInt) {
4264 uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
4265 *--current = '-';
4266 } else if (value < 0) {
4267 uintToString(LargestUInt(-value), current);
4268 *--current = '-';
4269 } else {
4270 uintToString(LargestUInt(value), current);
4271 }
4272 assert(current >= buffer);
4273 return current;
4274 }
4275
4276 JSONCPP_STRING valueToString(LargestUInt value) {
4277 UIntToStringBuffer buffer;
4278 char* current = buffer + sizeof(buffer);
4279 uintToString(value, current);
4280 assert(current >= buffer);
4281 return current;
4282 }
4283
4284 #if defined(JSON_HAS_INT64)
4285
4286 JSONCPP_STRING valueToString(Int value) {
4287 return valueToString(LargestInt(value));
4288 }
4289
4290 JSONCPP_STRING valueToString(UInt value) {
4291 return valueToString(LargestUInt(value));
4292 }
4293
4294 #endif
4295
4296 namespace {
4297 JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision, PrecisionType precisionType) {
4298
4299
4300 char buffer[36];
4301 int len = -1;
4302
4303 char formatString[15];
4304 if (precisionType == PrecisionType::significantDigits) {
4305 snprintf(formatString, sizeof(formatString), "%%.%ug", precision);
4306 } else {
4307 snprintf(formatString, sizeof(formatString), "%%.%uf", precision);
4308 }
4309
4310
4311
4312
4313 if (isfinite(value)) {
4314 len = snprintf(buffer, sizeof(buffer), formatString, value);
4315 fixNumericLocale(buffer, buffer + len);
4316
4317 if (precisionType == PrecisionType::decimalPlaces) {
4318 fixZerosInTheEnd(buffer, buffer + len);
4319 }
4320
4321
4322 if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
4323 strcat(buffer, ".0");
4324 }
4325
4326 } else {
4327
4328 if (value != value) {
4329 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
4330 } else if (value < 0) {
4331 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
4332 } else {
4333 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
4334 }
4335 }
4336 assert(len >= 0);
4337 return buffer;
4338 }
4339 }
4340
4341 JSONCPP_STRING valueToString(double value, unsigned int precision, PrecisionType precisionType) {
4342 return valueToString(value, false, precision, precisionType);
4343 }
4344
4345 JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
4346
4347 static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
4348 assert(s || !n);
4349
4350 char const* const end = s + n;
4351 for (char const* cur = s; cur < end; ++cur) {
4352 if (*cur == '\\' || *cur == '\"' || *cur < ' '
4353 || static_cast<unsigned char>(*cur) < 0x80)
4354 return true;
4355 }
4356 return false;
4357 }
4358
4359 static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
4360 const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
4361
4362 unsigned int firstByte = static_cast<unsigned char>(*s);
4363
4364 if (firstByte < 0x80)
4365 return firstByte;
4366
4367 if (firstByte < 0xE0) {
4368 if (e - s < 2)
4369 return REPLACEMENT_CHARACTER;
4370
4371 unsigned int calculated = ((firstByte & 0x1F) << 6)
4372 | (static_cast<unsigned int>(s[1]) & 0x3F);
4373 s += 1;
4374
4375 return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
4376 }
4377
4378 if (firstByte < 0xF0) {
4379 if (e - s < 3)
4380 return REPLACEMENT_CHARACTER;
4381
4382 unsigned int calculated = ((firstByte & 0x0F) << 12)
4383 | ((static_cast<unsigned int>(s[1]) & 0x3F) << 6)
4384 | (static_cast<unsigned int>(s[2]) & 0x3F);
4385 s += 2;
4386
4387
4388 if (calculated >= 0xD800 && calculated <= 0xDFFF)
4389 return REPLACEMENT_CHARACTER;
4390
4391 return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
4392 }
4393
4394 if (firstByte < 0xF8) {
4395 if (e - s < 4)
4396 return REPLACEMENT_CHARACTER;
4397
4398 unsigned int calculated = ((firstByte & 0x07) << 18)
4399 | ((static_cast<unsigned int>(s[1]) & 0x3F) << 12)
4400 | ((static_cast<unsigned int>(s[2]) & 0x3F) << 6)
4401 | (static_cast<unsigned int>(s[3]) & 0x3F);
4402 s += 3;
4403
4404 return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
4405 }
4406
4407 return REPLACEMENT_CHARACTER;
4408 }
4409
4410 static const char hex2[] =
4411 "000102030405060708090a0b0c0d0e0f"
4412 "101112131415161718191a1b1c1d1e1f"
4413 "202122232425262728292a2b2c2d2e2f"
4414 "303132333435363738393a3b3c3d3e3f"
4415 "404142434445464748494a4b4c4d4e4f"
4416 "505152535455565758595a5b5c5d5e5f"
4417 "606162636465666768696a6b6c6d6e6f"
4418 "707172737475767778797a7b7c7d7e7f"
4419 "808182838485868788898a8b8c8d8e8f"
4420 "909192939495969798999a9b9c9d9e9f"
4421 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
4422 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
4423 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
4424 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
4425 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
4426 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
4427
4428 static JSONCPP_STRING toHex16Bit(unsigned int x) {
4429 const unsigned int hi = (x >> 8) & 0xff;
4430 const unsigned int lo = x & 0xff;
4431 JSONCPP_STRING result(4, ' ');
4432 result[0] = hex2[2 * hi];
4433 result[1] = hex2[2 * hi + 1];
4434 result[2] = hex2[2 * lo];
4435 result[3] = hex2[2 * lo + 1];
4436 return result;
4437 }
4438
4439 static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
4440 if (value == NULL)
4441 return "";
4442
4443 if (!isAnyCharRequiredQuoting(value, length))
4444 return JSONCPP_STRING("\"") + value + "\"";
4445
4446
4447
4448 JSONCPP_STRING::size_type maxsize =
4449 length * 2 + 3;
4450 JSONCPP_STRING result;
4451 result.reserve(maxsize);
4452 result += "\"";
4453 char const* end = value + length;
4454 for (const char* c = value; c != end; ++c) {
4455 switch (*c) {
4456 case '\"':
4457 result += "\\\"";
4458 break;
4459 case '\\':
4460 result += "\\\\";
4461 break;
4462 case '\b':
4463 result += "\\b";
4464 break;
4465 case '\f':
4466 result += "\\f";
4467 break;
4468 case '\n':
4469 result += "\\n";
4470 break;
4471 case '\r':
4472 result += "\\r";
4473 break;
4474 case '\t':
4475 result += "\\t";
4476 break;
4477
4478
4479
4480
4481
4482
4483
4484
4485 default: {
4486 unsigned int cp = utf8ToCodepoint(c, end);
4487
4488
4489 if (cp < 0x80 && cp >= 0x20)
4490 result += static_cast<char>(cp);
4491 else if (cp < 0x10000) {
4492 result += "\\u";
4493 result += toHex16Bit(cp);
4494 }
4495 else {
4496
4497 cp -= 0x10000;
4498 result += "\\u";
4499 result += toHex16Bit((cp >> 10) + 0xD800);
4500 result += "\\u";
4501 result += toHex16Bit((cp & 0x3FF) + 0xDC00);
4502 }
4503 }
4504 break;
4505 }
4506 }
4507 result += "\"";
4508 return result;
4509 }
4510
4511 JSONCPP_STRING valueToQuotedString(const char* value) {
4512 return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
4513 }
4514
4515
4516
4517 Writer::~Writer() {}
4518
4519
4520
4521
4522 FastWriter::FastWriter()
4523 : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
4524 omitEndingLineFeed_(false) {}
4525
4526 void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
4527
4528 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
4529
4530 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
4531
4532 JSONCPP_STRING FastWriter::write(const Value& root) {
4533 document_.clear();
4534 writeValue(root);
4535 if (!omitEndingLineFeed_)
4536 document_ += "\n";
4537 return document_;
4538 }
4539
4540 void FastWriter::writeValue(const Value& value) {
4541 switch (value.type()) {
4542 case nullValue:
4543 if (!dropNullPlaceholders_)
4544 document_ += "null";
4545 break;
4546 case intValue:
4547 document_ += valueToString(value.asLargestInt());
4548 break;
4549 case uintValue:
4550 document_ += valueToString(value.asLargestUInt());
4551 break;
4552 case realValue:
4553 document_ += valueToString(value.asDouble());
4554 break;
4555 case stringValue:
4556 {
4557
4558 char const* str;
4559 char const* end;
4560 bool ok = value.getString(&str, &end);
4561 if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
4562 break;
4563 }
4564 case booleanValue:
4565 document_ += valueToString(value.asBool());
4566 break;
4567 case arrayValue: {
4568 document_ += '[';
4569 ArrayIndex size = value.size();
4570 for (ArrayIndex index = 0; index < size; ++index) {
4571 if (index > 0)
4572 document_ += ',';
4573 writeValue(value[index]);
4574 }
4575 document_ += ']';
4576 } break;
4577 case objectValue: {
4578 Value::Members members(value.getMemberNames());
4579 document_ += '{';
4580 for (Value::Members::iterator it = members.begin(); it != members.end();
4581 ++it) {
4582 const JSONCPP_STRING& name = *it;
4583 if (it != members.begin())
4584 document_ += ',';
4585 document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
4586 document_ += yamlCompatibilityEnabled_ ? ": " : ":";
4587 writeValue(value[name]);
4588 }
4589 document_ += '}';
4590 } break;
4591 }
4592 }
4593
4594
4595
4596
4597 StyledWriter::StyledWriter()
4598 : rightMargin_(74), indentSize_(3), addChildValues_() {}
4599
4600 JSONCPP_STRING StyledWriter::write(const Value& root) {
4601 document_.clear();
4602 addChildValues_ = false;
4603 indentString_.clear();
4604 writeCommentBeforeValue(root);
4605 writeValue(root);
4606 writeCommentAfterValueOnSameLine(root);
4607 document_ += "\n";
4608 return document_;
4609 }
4610
4611 void StyledWriter::writeValue(const Value& value) {
4612 switch (value.type()) {
4613 case nullValue:
4614 pushValue("null");
4615 break;
4616 case intValue:
4617 pushValue(valueToString(value.asLargestInt()));
4618 break;
4619 case uintValue:
4620 pushValue(valueToString(value.asLargestUInt()));
4621 break;
4622 case realValue:
4623 pushValue(valueToString(value.asDouble()));
4624 break;
4625 case stringValue:
4626 {
4627
4628 char const* str;
4629 char const* end;
4630 bool ok = value.getString(&str, &end);
4631 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4632 else pushValue("");
4633 break;
4634 }
4635 case booleanValue:
4636 pushValue(valueToString(value.asBool()));
4637 break;
4638 case arrayValue:
4639 writeArrayValue(value);
4640 break;
4641 case objectValue: {
4642 Value::Members members(value.getMemberNames());
4643 if (members.empty())
4644 pushValue("{}");
4645 else {
4646 writeWithIndent("{");
4647 indent();
4648 Value::Members::iterator it = members.begin();
4649 for (;;) {
4650 const JSONCPP_STRING& name = *it;
4651 const Value& childValue = value[name];
4652 writeCommentBeforeValue(childValue);
4653 writeWithIndent(valueToQuotedString(name.c_str()));
4654 document_ += " : ";
4655 writeValue(childValue);
4656 if (++it == members.end()) {
4657 writeCommentAfterValueOnSameLine(childValue);
4658 break;
4659 }
4660 document_ += ',';
4661 writeCommentAfterValueOnSameLine(childValue);
4662 }
4663 unindent();
4664 writeWithIndent("}");
4665 }
4666 } break;
4667 }
4668 }
4669
4670 void StyledWriter::writeArrayValue(const Value& value) {
4671 unsigned size = value.size();
4672 if (size == 0)
4673 pushValue("[]");
4674 else {
4675 bool isArrayMultiLine = isMultilineArray(value);
4676 if (isArrayMultiLine) {
4677 writeWithIndent("[");
4678 indent();
4679 bool hasChildValue = !childValues_.empty();
4680 unsigned index = 0;
4681 for (;;) {
4682 const Value& childValue = value[index];
4683 writeCommentBeforeValue(childValue);
4684 if (hasChildValue)
4685 writeWithIndent(childValues_[index]);
4686 else {
4687 writeIndent();
4688 writeValue(childValue);
4689 }
4690 if (++index == size) {
4691 writeCommentAfterValueOnSameLine(childValue);
4692 break;
4693 }
4694 document_ += ',';
4695 writeCommentAfterValueOnSameLine(childValue);
4696 }
4697 unindent();
4698 writeWithIndent("]");
4699 } else
4700 {
4701 assert(childValues_.size() == size);
4702 document_ += "[ ";
4703 for (unsigned index = 0; index < size; ++index) {
4704 if (index > 0)
4705 document_ += ", ";
4706 document_ += childValues_[index];
4707 }
4708 document_ += " ]";
4709 }
4710 }
4711 }
4712
4713 bool StyledWriter::isMultilineArray(const Value& value) {
4714 ArrayIndex const size = value.size();
4715 bool isMultiLine = size * 3 >= rightMargin_;
4716 childValues_.clear();
4717 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
4718 const Value& childValue = value[index];
4719 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4720 childValue.size() > 0);
4721 }
4722 if (!isMultiLine)
4723 {
4724 childValues_.reserve(size);
4725 addChildValues_ = true;
4726 ArrayIndex lineLength = 4 + (size - 1) * 2;
4727 for (ArrayIndex index = 0; index < size; ++index) {
4728 if (hasCommentForValue(value[index])) {
4729 isMultiLine = true;
4730 }
4731 writeValue(value[index]);
4732 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
4733 }
4734 addChildValues_ = false;
4735 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4736 }
4737 return isMultiLine;
4738 }
4739
4740 void StyledWriter::pushValue(const JSONCPP_STRING& value) {
4741 if (addChildValues_)
4742 childValues_.push_back(value);
4743 else
4744 document_ += value;
4745 }
4746
4747 void StyledWriter::writeIndent() {
4748 if (!document_.empty()) {
4749 char last = document_[document_.length() - 1];
4750 if (last == ' ')
4751 return;
4752 if (last != '\n')
4753 document_ += '\n';
4754 }
4755 document_ += indentString_;
4756 }
4757
4758 void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
4759 writeIndent();
4760 document_ += value;
4761 }
4762
4763 void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
4764
4765 void StyledWriter::unindent() {
4766 assert(indentString_.size() >= indentSize_);
4767 indentString_.resize(indentString_.size() - indentSize_);
4768 }
4769
4770 void StyledWriter::writeCommentBeforeValue(const Value& root) {
4771 if (!root.hasComment(commentBefore))
4772 return;
4773
4774 document_ += "\n";
4775 writeIndent();
4776 const JSONCPP_STRING& comment = root.getComment(commentBefore);
4777 JSONCPP_STRING::const_iterator iter = comment.begin();
4778 while (iter != comment.end()) {
4779 document_ += *iter;
4780 if (*iter == '\n' &&
4781 ((iter+1) != comment.end() && *(iter + 1) == '/'))
4782 writeIndent();
4783 ++iter;
4784 }
4785
4786
4787 document_ += "\n";
4788 }
4789
4790 void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
4791 if (root.hasComment(commentAfterOnSameLine))
4792 document_ += " " + root.getComment(commentAfterOnSameLine);
4793
4794 if (root.hasComment(commentAfter)) {
4795 document_ += "\n";
4796 document_ += root.getComment(commentAfter);
4797 document_ += "\n";
4798 }
4799 }
4800
4801 bool StyledWriter::hasCommentForValue(const Value& value) {
4802 return value.hasComment(commentBefore) ||
4803 value.hasComment(commentAfterOnSameLine) ||
4804 value.hasComment(commentAfter);
4805 }
4806
4807
4808
4809
4810 StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
4811 : document_(NULL), rightMargin_(74), indentation_(indentation),
4812 addChildValues_(), indented_(false)
4813 {}
4814
4815 void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
4816 document_ = &out;
4817 addChildValues_ = false;
4818 indentString_.clear();
4819 indented_ = true;
4820 writeCommentBeforeValue(root);
4821 if (!indented_) writeIndent();
4822 indented_ = true;
4823 writeValue(root);
4824 writeCommentAfterValueOnSameLine(root);
4825 *document_ << "\n";
4826 document_ = NULL;
4827 }
4828
4829 void StyledStreamWriter::writeValue(const Value& value) {
4830 switch (value.type()) {
4831 case nullValue:
4832 pushValue("null");
4833 break;
4834 case intValue:
4835 pushValue(valueToString(value.asLargestInt()));
4836 break;
4837 case uintValue:
4838 pushValue(valueToString(value.asLargestUInt()));
4839 break;
4840 case realValue:
4841 pushValue(valueToString(value.asDouble()));
4842 break;
4843 case stringValue:
4844 {
4845
4846 char const* str;
4847 char const* end;
4848 bool ok = value.getString(&str, &end);
4849 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4850 else pushValue("");
4851 break;
4852 }
4853 case booleanValue:
4854 pushValue(valueToString(value.asBool()));
4855 break;
4856 case arrayValue:
4857 writeArrayValue(value);
4858 break;
4859 case objectValue: {
4860 Value::Members members(value.getMemberNames());
4861 if (members.empty())
4862 pushValue("{}");
4863 else {
4864 writeWithIndent("{");
4865 indent();
4866 Value::Members::iterator it = members.begin();
4867 for (;;) {
4868 const JSONCPP_STRING& name = *it;
4869 const Value& childValue = value[name];
4870 writeCommentBeforeValue(childValue);
4871 writeWithIndent(valueToQuotedString(name.c_str()));
4872 *document_ << " : ";
4873 writeValue(childValue);
4874 if (++it == members.end()) {
4875 writeCommentAfterValueOnSameLine(childValue);
4876 break;
4877 }
4878 *document_ << ",";
4879 writeCommentAfterValueOnSameLine(childValue);
4880 }
4881 unindent();
4882 writeWithIndent("}");
4883 }
4884 } break;
4885 }
4886 }
4887
4888 void StyledStreamWriter::writeArrayValue(const Value& value) {
4889 unsigned size = value.size();
4890 if (size == 0)
4891 pushValue("[]");
4892 else {
4893 bool isArrayMultiLine = isMultilineArray(value);
4894 if (isArrayMultiLine) {
4895 writeWithIndent("[");
4896 indent();
4897 bool hasChildValue = !childValues_.empty();
4898 unsigned index = 0;
4899 for (;;) {
4900 const Value& childValue = value[index];
4901 writeCommentBeforeValue(childValue);
4902 if (hasChildValue)
4903 writeWithIndent(childValues_[index]);
4904 else {
4905 if (!indented_) writeIndent();
4906 indented_ = true;
4907 writeValue(childValue);
4908 indented_ = false;
4909 }
4910 if (++index == size) {
4911 writeCommentAfterValueOnSameLine(childValue);
4912 break;
4913 }
4914 *document_ << ",";
4915 writeCommentAfterValueOnSameLine(childValue);
4916 }
4917 unindent();
4918 writeWithIndent("]");
4919 } else
4920 {
4921 assert(childValues_.size() == size);
4922 *document_ << "[ ";
4923 for (unsigned index = 0; index < size; ++index) {
4924 if (index > 0)
4925 *document_ << ", ";
4926 *document_ << childValues_[index];
4927 }
4928 *document_ << " ]";
4929 }
4930 }
4931 }
4932
4933 bool StyledStreamWriter::isMultilineArray(const Value& value) {
4934 ArrayIndex const size = value.size();
4935 bool isMultiLine = size * 3 >= rightMargin_;
4936 childValues_.clear();
4937 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
4938 const Value& childValue = value[index];
4939 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4940 childValue.size() > 0);
4941 }
4942 if (!isMultiLine)
4943 {
4944 childValues_.reserve(size);
4945 addChildValues_ = true;
4946 ArrayIndex lineLength = 4 + (size - 1) * 2;
4947 for (ArrayIndex index = 0; index < size; ++index) {
4948 if (hasCommentForValue(value[index])) {
4949 isMultiLine = true;
4950 }
4951 writeValue(value[index]);
4952 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
4953 }
4954 addChildValues_ = false;
4955 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4956 }
4957 return isMultiLine;
4958 }
4959
4960 void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
4961 if (addChildValues_)
4962 childValues_.push_back(value);
4963 else
4964 *document_ << value;
4965 }
4966
4967 void StyledStreamWriter::writeIndent() {
4968
4969
4970
4971
4972 *document_ << '\n' << indentString_;
4973 }
4974
4975 void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
4976 if (!indented_) writeIndent();
4977 *document_ << value;
4978 indented_ = false;
4979 }
4980
4981 void StyledStreamWriter::indent() { indentString_ += indentation_; }
4982
4983 void StyledStreamWriter::unindent() {
4984 assert(indentString_.size() >= indentation_.size());
4985 indentString_.resize(indentString_.size() - indentation_.size());
4986 }
4987
4988 void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
4989 if (!root.hasComment(commentBefore))
4990 return;
4991
4992 if (!indented_) writeIndent();
4993 const JSONCPP_STRING& comment = root.getComment(commentBefore);
4994 JSONCPP_STRING::const_iterator iter = comment.begin();
4995 while (iter != comment.end()) {
4996 *document_ << *iter;
4997 if (*iter == '\n' &&
4998 ((iter+1) != comment.end() && *(iter + 1) == '/'))
4999
5000 *document_ << indentString_;
5001 ++iter;
5002 }
5003 indented_ = false;
5004 }
5005
5006 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
5007 if (root.hasComment(commentAfterOnSameLine))
5008 *document_ << ' ' << root.getComment(commentAfterOnSameLine);
5009
5010 if (root.hasComment(commentAfter)) {
5011 writeIndent();
5012 *document_ << root.getComment(commentAfter);
5013 }
5014 indented_ = false;
5015 }
5016
5017 bool StyledStreamWriter::hasCommentForValue(const Value& value) {
5018 return value.hasComment(commentBefore) ||
5019 value.hasComment(commentAfterOnSameLine) ||
5020 value.hasComment(commentAfter);
5021 }
5022
5023
5024
5025
5026
5027 struct CommentStyle {
5028
5029 enum Enum {
5030 None,
5031 Most,
5032 All
5033 };
5034 };
5035
5036 struct BuiltStyledStreamWriter : public StreamWriter
5037 {
5038 BuiltStyledStreamWriter(
5039 JSONCPP_STRING const& indentation,
5040 CommentStyle::Enum cs,
5041 JSONCPP_STRING const& colonSymbol,
5042 JSONCPP_STRING const& nullSymbol,
5043 JSONCPP_STRING const& endingLineFeedSymbol,
5044 bool useSpecialFloats,
5045 unsigned int precision,
5046 PrecisionType precisionType);
5047 int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
5048 private:
5049 void writeValue(Value const& value);
5050 void writeArrayValue(Value const& value);
5051 bool isMultilineArray(Value const& value);
5052 void pushValue(JSONCPP_STRING const& value);
5053 void writeIndent();
5054 void writeWithIndent(JSONCPP_STRING const& value);
5055 void indent();
5056 void unindent();
5057 void writeCommentBeforeValue(Value const& root);
5058 void writeCommentAfterValueOnSameLine(Value const& root);
5059 static bool hasCommentForValue(const Value& value);
5060
5061 typedef std::vector<JSONCPP_STRING> ChildValues;
5062
5063 ChildValues childValues_;
5064 JSONCPP_STRING indentString_;
5065 unsigned int rightMargin_;
5066 JSONCPP_STRING indentation_;
5067 CommentStyle::Enum cs_;
5068 JSONCPP_STRING colonSymbol_;
5069 JSONCPP_STRING nullSymbol_;
5070 JSONCPP_STRING endingLineFeedSymbol_;
5071 bool addChildValues_ : 1;
5072 bool indented_ : 1;
5073 bool useSpecialFloats_ : 1;
5074 unsigned int precision_;
5075 PrecisionType precisionType_;
5076 };
5077 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
5078 JSONCPP_STRING const& indentation,
5079 CommentStyle::Enum cs,
5080 JSONCPP_STRING const& colonSymbol,
5081 JSONCPP_STRING const& nullSymbol,
5082 JSONCPP_STRING const& endingLineFeedSymbol,
5083 bool useSpecialFloats,
5084 unsigned int precision,
5085 PrecisionType precisionType)
5086 : rightMargin_(74)
5087 , indentation_(indentation)
5088 , cs_(cs)
5089 , colonSymbol_(colonSymbol)
5090 , nullSymbol_(nullSymbol)
5091 , endingLineFeedSymbol_(endingLineFeedSymbol)
5092 , addChildValues_(false)
5093 , indented_(false)
5094 , useSpecialFloats_(useSpecialFloats)
5095 , precision_(precision)
5096 , precisionType_(precisionType)
5097 {
5098 }
5099 int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
5100 {
5101 sout_ = sout;
5102 addChildValues_ = false;
5103 indented_ = true;
5104 indentString_.clear();
5105 writeCommentBeforeValue(root);
5106 if (!indented_) writeIndent();
5107 indented_ = true;
5108 writeValue(root);
5109 writeCommentAfterValueOnSameLine(root);
5110 *sout_ << endingLineFeedSymbol_;
5111 sout_ = NULL;
5112 return 0;
5113 }
5114 void BuiltStyledStreamWriter::writeValue(Value const& value) {
5115 switch (value.type()) {
5116 case nullValue:
5117 pushValue(nullSymbol_);
5118 break;
5119 case intValue:
5120 pushValue(valueToString(value.asLargestInt()));
5121 break;
5122 case uintValue:
5123 pushValue(valueToString(value.asLargestUInt()));
5124 break;
5125 case realValue:
5126 pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, precisionType_));
5127 break;
5128 case stringValue:
5129 {
5130
5131 char const* str;
5132 char const* end;
5133 bool ok = value.getString(&str, &end);
5134 if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
5135 else pushValue("");
5136 break;
5137 }
5138 case booleanValue:
5139 pushValue(valueToString(value.asBool()));
5140 break;
5141 case arrayValue:
5142 writeArrayValue(value);
5143 break;
5144 case objectValue: {
5145 Value::Members members(value.getMemberNames());
5146 if (members.empty())
5147 pushValue("{}");
5148 else {
5149 writeWithIndent("{");
5150 indent();
5151 Value::Members::iterator it = members.begin();
5152 for (;;) {
5153 JSONCPP_STRING const& name = *it;
5154 Value const& childValue = value[name];
5155 writeCommentBeforeValue(childValue);
5156 writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
5157 *sout_ << colonSymbol_;
5158 writeValue(childValue);
5159 if (++it == members.end()) {
5160 writeCommentAfterValueOnSameLine(childValue);
5161 break;
5162 }
5163 *sout_ << ",";
5164 writeCommentAfterValueOnSameLine(childValue);
5165 }
5166 unindent();
5167 writeWithIndent("}");
5168 }
5169 } break;
5170 }
5171 }
5172
5173 void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
5174 unsigned size = value.size();
5175 if (size == 0)
5176 pushValue("[]");
5177 else {
5178 bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
5179 if (isMultiLine) {
5180 writeWithIndent("[");
5181 indent();
5182 bool hasChildValue = !childValues_.empty();
5183 unsigned index = 0;
5184 for (;;) {
5185 Value const& childValue = value[index];
5186 writeCommentBeforeValue(childValue);
5187 if (hasChildValue)
5188 writeWithIndent(childValues_[index]);
5189 else {
5190 if (!indented_) writeIndent();
5191 indented_ = true;
5192 writeValue(childValue);
5193 indented_ = false;
5194 }
5195 if (++index == size) {
5196 writeCommentAfterValueOnSameLine(childValue);
5197 break;
5198 }
5199 *sout_ << ",";
5200 writeCommentAfterValueOnSameLine(childValue);
5201 }
5202 unindent();
5203 writeWithIndent("]");
5204 } else
5205 {
5206 assert(childValues_.size() == size);
5207 *sout_ << "[";
5208 if (!indentation_.empty()) *sout_ << " ";
5209 for (unsigned index = 0; index < size; ++index) {
5210 if (index > 0)
5211 *sout_ << ((!indentation_.empty()) ? ", " : ",");
5212 *sout_ << childValues_[index];
5213 }
5214 if (!indentation_.empty()) *sout_ << " ";
5215 *sout_ << "]";
5216 }
5217 }
5218 }
5219
5220 bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
5221 ArrayIndex const size = value.size();
5222 bool isMultiLine = size * 3 >= rightMargin_;
5223 childValues_.clear();
5224 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
5225 Value const& childValue = value[index];
5226 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
5227 childValue.size() > 0);
5228 }
5229 if (!isMultiLine)
5230 {
5231 childValues_.reserve(size);
5232 addChildValues_ = true;
5233 ArrayIndex lineLength = 4 + (size - 1) * 2;
5234 for (ArrayIndex index = 0; index < size; ++index) {
5235 if (hasCommentForValue(value[index])) {
5236 isMultiLine = true;
5237 }
5238 writeValue(value[index]);
5239 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
5240 }
5241 addChildValues_ = false;
5242 isMultiLine = isMultiLine || lineLength >= rightMargin_;
5243 }
5244 return isMultiLine;
5245 }
5246
5247 void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
5248 if (addChildValues_)
5249 childValues_.push_back(value);
5250 else
5251 *sout_ << value;
5252 }
5253
5254 void BuiltStyledStreamWriter::writeIndent() {
5255
5256
5257
5258
5259
5260 if (!indentation_.empty()) {
5261
5262 *sout_ << '\n' << indentString_;
5263 }
5264 }
5265
5266 void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
5267 if (!indented_) writeIndent();
5268 *sout_ << value;
5269 indented_ = false;
5270 }
5271
5272 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
5273
5274 void BuiltStyledStreamWriter::unindent() {
5275 assert(indentString_.size() >= indentation_.size());
5276 indentString_.resize(indentString_.size() - indentation_.size());
5277 }
5278
5279 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
5280 if (cs_ == CommentStyle::None) return;
5281 if (!root.hasComment(commentBefore))
5282 return;
5283
5284 if (!indented_) writeIndent();
5285 const JSONCPP_STRING& comment = root.getComment(commentBefore);
5286 JSONCPP_STRING::const_iterator iter = comment.begin();
5287 while (iter != comment.end()) {
5288 *sout_ << *iter;
5289 if (*iter == '\n' &&
5290 ((iter+1) != comment.end() && *(iter + 1) == '/'))
5291
5292 *sout_ << indentString_;
5293 ++iter;
5294 }
5295 indented_ = false;
5296 }
5297
5298 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
5299 if (cs_ == CommentStyle::None) return;
5300 if (root.hasComment(commentAfterOnSameLine))
5301 *sout_ << " " + root.getComment(commentAfterOnSameLine);
5302
5303 if (root.hasComment(commentAfter)) {
5304 writeIndent();
5305 *sout_ << root.getComment(commentAfter);
5306 }
5307 }
5308
5309
5310 bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
5311 return value.hasComment(commentBefore) ||
5312 value.hasComment(commentAfterOnSameLine) ||
5313 value.hasComment(commentAfter);
5314 }
5315
5316
5317
5318
5319 StreamWriter::StreamWriter()
5320 : sout_(NULL)
5321 {
5322 }
5323 StreamWriter::~StreamWriter()
5324 {
5325 }
5326 StreamWriter::Factory::~Factory()
5327 {}
5328 StreamWriterBuilder::StreamWriterBuilder()
5329 {
5330 setDefaults(&settings_);
5331 }
5332 StreamWriterBuilder::~StreamWriterBuilder()
5333 {}
5334 StreamWriter* StreamWriterBuilder::newStreamWriter() const
5335 {
5336 JSONCPP_STRING indentation = settings_["indentation"].asString();
5337 JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
5338 JSONCPP_STRING pt_str = settings_["precisionType"].asString();
5339 bool eyc = settings_["enableYAMLCompatibility"].asBool();
5340 bool dnp = settings_["dropNullPlaceholders"].asBool();
5341 bool usf = settings_["useSpecialFloats"].asBool();
5342 unsigned int pre = settings_["precision"].asUInt();
5343 CommentStyle::Enum cs = CommentStyle::All;
5344 if (cs_str == "All") {
5345 cs = CommentStyle::All;
5346 } else if (cs_str == "None") {
5347 cs = CommentStyle::None;
5348 } else {
5349 throwRuntimeError("commentStyle must be 'All' or 'None'");
5350 }
5351 PrecisionType precisionType(significantDigits);
5352 if (pt_str == "significant") {
5353 precisionType = PrecisionType::significantDigits;
5354 } else if (pt_str == "decimal") {
5355 precisionType = PrecisionType::decimalPlaces;
5356 } else {
5357 throwRuntimeError("precisionType must be 'significant' or 'decimal'");
5358 }
5359 JSONCPP_STRING colonSymbol = " : ";
5360 if (eyc) {
5361 colonSymbol = ": ";
5362 } else if (indentation.empty()) {
5363 colonSymbol = ":";
5364 }
5365 JSONCPP_STRING nullSymbol = "null";
5366 if (dnp) {
5367 nullSymbol.clear();
5368 }
5369 if (pre > 17) pre = 17;
5370 JSONCPP_STRING endingLineFeedSymbol;
5371 return new BuiltStyledStreamWriter(
5372 indentation, cs,
5373 colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre, precisionType);
5374 }
5375 static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
5376 {
5377 valid_keys->clear();
5378 valid_keys->insert("indentation");
5379 valid_keys->insert("commentStyle");
5380 valid_keys->insert("enableYAMLCompatibility");
5381 valid_keys->insert("dropNullPlaceholders");
5382 valid_keys->insert("useSpecialFloats");
5383 valid_keys->insert("precision");
5384 valid_keys->insert("precisionType");
5385 }
5386 bool StreamWriterBuilder::validate(Json::Value* invalid) const
5387 {
5388 Json::Value my_invalid;
5389 if (!invalid) invalid = &my_invalid;
5390 Json::Value& inv = *invalid;
5391 std::set<JSONCPP_STRING> valid_keys;
5392 getValidWriterKeys(&valid_keys);
5393 Value::Members keys = settings_.getMemberNames();
5394 size_t n = keys.size();
5395 for (size_t i = 0; i < n; ++i) {
5396 JSONCPP_STRING const& key = keys[i];
5397 if (valid_keys.find(key) == valid_keys.end()) {
5398 inv[key] = settings_[key];
5399 }
5400 }
5401 return 0u == inv.size();
5402 }
5403 Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
5404 {
5405 return settings_[key];
5406 }
5407
5408 void StreamWriterBuilder::setDefaults(Json::Value* settings)
5409 {
5410
5411 (*settings)["commentStyle"] = "All";
5412 (*settings)["indentation"] = "\t";
5413 (*settings)["enableYAMLCompatibility"] = false;
5414 (*settings)["dropNullPlaceholders"] = false;
5415 (*settings)["useSpecialFloats"] = false;
5416 (*settings)["precision"] = 17;
5417 (*settings)["precisionType"] = "significant";
5418
5419 }
5420
5421 JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
5422 JSONCPP_OSTRINGSTREAM sout;
5423 StreamWriterPtr const writer(builder.newStreamWriter());
5424 writer->write(root, &sout);
5425 return sout.str();
5426 }
5427
5428 JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
5429 StreamWriterBuilder builder;
5430 StreamWriterPtr const writer(builder.newStreamWriter());
5431 writer->write(root, &sout);
5432 return sout;
5433 }
5434
5435 }
5436
5437
5438
5439
5440
5441
5442
5443
5444