6 #if !defined(JSON_IS_AMALGAMATION)
11 #endif // if !defined(JSON_IS_AMALGAMATION)
23 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
24 #define snprintf sprintf_s
25 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
26 #define snprintf std::snprintf
28 #define snprintf _snprintf
30 #elif defined(__ANDROID__) || defined(__QNXNTO__)
31 #define snprintf snprintf
32 #elif __cplusplus >= 201103L
33 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
34 #define snprintf std::snprintf
38 #if defined(__QNXNTO__)
39 #define sscanf std::sscanf
42 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
44 #pragma warning(disable : 4996)
52 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
62 : allowComments_(true), strictRoot_(false),
63 allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
80 for (; begin < end; ++begin)
81 if (*begin ==
'\n' || *begin ==
'\r')
90 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
91 lastValue_(), commentsBefore_(), features_(
Features::all()),
95 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
96 lastValue_(), commentsBefore_(), features_(features), collectComments_() {
101 JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
102 std::swap(documentCopy, document_);
103 const char* begin = document_.c_str();
104 const char* end = begin + document_.length();
105 return parse(begin, end, root, collectComments);
117 std::getline(sin, doc, (
char)EOF);
118 return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
124 bool collectComments) {
126 collectComments =
false;
131 collectComments_ = collectComments;
135 commentsBefore_ =
"";
137 while (!nodes_.empty())
142 bool successful = readValue();
144 skipCommentTokens(token);
145 if (collectComments_ && !commentsBefore_.empty())
151 token.type_ = tokenError;
152 token.start_ = beginDoc;
155 "A valid JSON document must be either an array or an object value.",
163 bool Reader::readValue() {
172 skipCommentTokens(token);
173 bool successful =
true;
175 if (collectComments_ && !commentsBefore_.empty()) {
177 commentsBefore_ =
"";
180 switch (token.type_) {
181 case tokenObjectBegin:
182 successful = readObject(token);
185 case tokenArrayBegin:
186 successful = readArray(token);
190 successful = decodeNumber(token);
193 successful = decodeString(token);
219 case tokenArraySeparator:
235 return addError(
"Syntax error: value, object or array expected.", token);
238 if (collectComments_) {
239 lastValueEnd_ = current_;
240 lastValue_ = ¤tValue();
247 void Reader::skipCommentTokens(Token& token) {
251 }
while (token.type_ == tokenComment);
257 bool Reader::readToken(Token& token) {
259 token.start_ = current_;
260 Char c = getNextChar();
264 token.type_ = tokenObjectBegin;
267 token.type_ = tokenObjectEnd;
270 token.type_ = tokenArrayBegin;
273 token.type_ = tokenArrayEnd;
276 token.type_ = tokenString;
280 token.type_ = tokenComment;
294 token.type_ = tokenNumber;
298 token.type_ = tokenTrue;
299 ok = match(
"rue", 3);
302 token.type_ = tokenFalse;
303 ok = match(
"alse", 4);
306 token.type_ = tokenNull;
307 ok = match(
"ull", 3);
310 token.type_ = tokenArraySeparator;
313 token.type_ = tokenMemberSeparator;
316 token.type_ = tokenEndOfStream;
323 token.type_ = tokenError;
324 token.end_ = current_;
328 void Reader::skipSpaces() {
329 while (current_ != end_) {
331 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
338 bool Reader::match(Location pattern,
int patternLength) {
339 if (end_ - current_ < patternLength)
341 int index = patternLength;
343 if (current_[index] != pattern[index])
345 current_ += patternLength;
349 bool Reader::readComment() {
350 Location commentBegin = current_ - 1;
351 Char c = getNextChar();
352 bool successful =
false;
354 successful = readCStyleComment();
356 successful = readCppStyleComment();
360 if (collectComments_) {
367 addComment(commentBegin, current_, placement);
374 normalized.reserve(
static_cast<size_t>(end - begin));
376 while (current != end) {
379 if (current != end && *current ==
'\n')
392 Reader::addComment(Location begin, Location end,
CommentPlacement placement) {
393 assert(collectComments_);
396 assert(lastValue_ != 0);
397 lastValue_->
setComment(normalized, placement);
399 commentsBefore_ += normalized;
403 bool Reader::readCStyleComment() {
404 while (current_ != end_) {
405 Char c = getNextChar();
406 if (c ==
'*' && *current_ ==
'/')
409 return getNextChar() ==
'/';
412 bool Reader::readCppStyleComment() {
413 while (current_ != end_) {
414 Char c = getNextChar();
419 if (current_ != end_ && *current_ ==
'\n')
428 void Reader::readNumber() {
429 const char *p = current_;
432 while (c >=
'0' && c <=
'9')
433 c = (current_ = p) < end_ ? *p++ :
'\0';
436 c = (current_ = p) < end_ ? *p++ :
'\0';
437 while (c >=
'0' && c <=
'9')
438 c = (current_ = p) < end_ ? *p++ :
'\0';
441 if (c ==
'e' || c ==
'E') {
442 c = (current_ = p) < end_ ? *p++ :
'\0';
443 if (c ==
'+' || c ==
'-')
444 c = (current_ = p) < end_ ? *p++ :
'\0';
445 while (c >=
'0' && c <=
'9')
446 c = (current_ = p) < end_ ? *p++ :
'\0';
450 bool Reader::readString() {
452 while (current_ != end_) {
462 bool Reader::readObject(Token& tokenStart) {
468 while (readToken(tokenName)) {
469 bool initialTokenOk =
true;
470 while (tokenName.type_ == tokenComment && initialTokenOk)
471 initialTokenOk = readToken(tokenName);
474 if (tokenName.type_ == tokenObjectEnd && name.empty())
477 if (tokenName.type_ == tokenString) {
478 if (!decodeString(tokenName, name))
479 return recoverFromError(tokenObjectEnd);
482 if (!decodeNumber(tokenName, numberName))
483 return recoverFromError(tokenObjectEnd);
490 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
491 return addErrorAndRecover(
492 "Missing ':' after object member name", colon, tokenObjectEnd);
494 Value& value = currentValue()[name];
496 bool ok = readValue();
499 return recoverFromError(tokenObjectEnd);
502 if (!readToken(comma) ||
503 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
504 comma.type_ != tokenComment)) {
505 return addErrorAndRecover(
506 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
508 bool finalizeTokenOk =
true;
509 while (comma.type_ == tokenComment && finalizeTokenOk)
510 finalizeTokenOk = readToken(comma);
511 if (comma.type_ == tokenObjectEnd)
514 return addErrorAndRecover(
515 "Missing '}' or object member name", tokenName, tokenObjectEnd);
518 bool Reader::readArray(Token& tokenStart) {
523 if (*current_ ==
']')
531 Value& value = currentValue()[index++];
533 bool ok = readValue();
536 return recoverFromError(tokenArrayEnd);
540 ok = readToken(token);
541 while (token.type_ == tokenComment && ok) {
542 ok = readToken(token);
545 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
546 if (!ok || badTokenType) {
547 return addErrorAndRecover(
548 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
550 if (token.type_ == tokenArrayEnd)
556 bool Reader::decodeNumber(Token& token) {
558 if (!decodeNumber(token, decoded))
566 bool Reader::decodeNumber(Token& token, Value& decoded) {
571 bool isNegative = *current ==
'-';
580 while (current < token.end_) {
582 if (c < '0' || c >
'9')
583 return decodeDouble(token, decoded);
585 if (value >= threshold) {
590 if (value > threshold || current != token.end_ ||
591 digit > maxIntegerValue % 10) {
592 return decodeDouble(token, decoded);
595 value = value * 10 + digit;
597 if (isNegative && value == maxIntegerValue)
608 bool Reader::decodeDouble(Token& token) {
610 if (!decodeDouble(token, decoded))
618 bool Reader::decodeDouble(Token& token, Value& decoded) {
624 "' is not a number.",
630 bool Reader::decodeString(Token& token) {
632 if (!decodeString(token, decoded_string))
634 Value decoded(decoded_string);
641 bool Reader::decodeString(Token& token,
JSONCPP_STRING& decoded) {
642 decoded.reserve(
static_cast<size_t>(token.end_ - token.start_ - 2));
643 Location current = token.start_ + 1;
645 while (current != end) {
649 else if (c ==
'\\') {
651 return addError(
"Empty escape sequence in string", token, current);
652 Char escape = *current++;
679 unsigned int unicode;
680 if (!decodeUnicodeCodePoint(token, current, end, unicode))
685 return addError(
"Bad escape sequence in string", token, current);
694 bool Reader::decodeUnicodeCodePoint(Token& token,
697 unsigned int& unicode) {
699 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
701 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
703 if (end - current < 6)
705 "additional six characters expected to parse unicode surrogate pair.",
708 unsigned int surrogatePair;
709 if (*(current++) ==
'\\' && *(current++) ==
'u') {
710 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
711 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
715 return addError(
"expecting another \\u token to begin the second half of "
716 "a unicode surrogate pair",
723 bool Reader::decodeUnicodeEscapeSequence(Token& token,
726 unsigned int& ret_unicode) {
727 if (end - current < 4)
729 "Bad unicode escape sequence in string: four digits expected.",
733 for (
int index = 0; index < 4; ++index) {
736 if (c >=
'0' && c <=
'9')
738 else if (c >=
'a' && c <=
'f')
739 unicode += c -
'a' + 10;
740 else if (c >=
'A' && c <=
'F')
741 unicode += c -
'A' + 10;
744 "Bad unicode escape sequence in string: hexadecimal digit expected.",
748 ret_unicode =
static_cast<unsigned int>(unicode);
753 Reader::addError(
const JSONCPP_STRING& message, Token& token, Location extra) {
756 info.message_ = message;
758 errors_.push_back(info);
762 bool Reader::recoverFromError(TokenType skipUntilToken) {
763 size_t const errorCount = errors_.size();
766 if (!readToken(skip))
767 errors_.resize(errorCount);
768 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
771 errors_.resize(errorCount);
777 TokenType skipUntilToken) {
778 addError(message, token);
779 return recoverFromError(skipUntilToken);
782 Value& Reader::currentValue() {
return *(nodes_.top()); }
785 if (current_ == end_)
790 void Reader::getLocationLineAndColumn(Location location,
796 while (current < location && current != end_) {
799 if (*current ==
'\n')
801 lastLineStart = current;
803 }
else if (c ==
'\n') {
804 lastLineStart = current;
809 column = int(location - lastLineStart) + 1;
813 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location)
const {
815 getLocationLineAndColumn(location, line, column);
816 char buffer[18 + 16 + 16 + 1];
817 snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
828 for (Errors::const_iterator itError = errors_.begin();
829 itError != errors_.end();
831 const ErrorInfo& error = *itError;
833 "* " + getLocationLineAndColumn(error.token_.start_) +
"\n";
834 formattedMessage +=
" " + error.message_ +
"\n";
837 "See " + getLocationLineAndColumn(error.extra_) +
" for detail.\n";
839 return formattedMessage;
843 std::vector<Reader::StructuredError> allErrors;
844 for (Errors::const_iterator itError = errors_.begin();
845 itError != errors_.end();
847 const ErrorInfo& error = *itError;
851 structured.
message = error.message_;
852 allErrors.push_back(structured);
858 ptrdiff_t
const length = end_ - begin_;
863 token.type_ = tokenError;
868 info.message_ = message;
870 errors_.push_back(info);
875 ptrdiff_t
const length = end_ - begin_;
881 token.type_ = tokenError;
886 info.message_ = message;
888 errors_.push_back(info);
893 return !errors_.size();
899 static OurFeatures all();
902 bool allowDroppedNullPlaceholders_;
903 bool allowNumericKeys_;
904 bool allowSingleQuotes_;
907 bool allowSpecialFloats_;
914 OurFeatures OurFeatures::all() {
return OurFeatures(); }
923 typedef const Char* Location;
924 struct StructuredError {
925 ptrdiff_t offset_start;
926 ptrdiff_t offset_limit;
930 OurReader(OurFeatures
const& features);
931 bool parse(
const char* beginDoc,
934 bool collectComments =
true);
936 std::vector<StructuredError> getStructuredErrors()
const;
937 bool pushError(
const Value& value,
const JSONCPP_STRING& message);
938 bool pushError(
const Value& value,
const JSONCPP_STRING& message,
const Value& extra);
942 OurReader(OurReader
const&);
943 void operator=(OurReader
const&);
946 tokenEndOfStream = 0,
960 tokenMemberSeparator,
979 typedef std::deque<ErrorInfo> Errors;
981 bool readToken(Token& token);
983 bool match(Location pattern,
int patternLength);
985 bool readCStyleComment();
986 bool readCppStyleComment();
988 bool readStringSingleQuote();
989 bool readNumber(
bool checkInf);
991 bool readObject(Token& token);
992 bool readArray(Token& token);
993 bool decodeNumber(Token& token);
994 bool decodeNumber(Token& token, Value& decoded);
995 bool decodeString(Token& token);
997 bool decodeDouble(Token& token);
998 bool decodeDouble(Token& token, Value& decoded);
999 bool decodeUnicodeCodePoint(Token& token,
1002 unsigned int& unicode);
1003 bool decodeUnicodeEscapeSequence(Token& token,
1006 unsigned int& unicode);
1007 bool addError(
const JSONCPP_STRING& message, Token& token, Location extra = 0);
1008 bool recoverFromError(TokenType skipUntilToken);
1011 TokenType skipUntilToken);
1012 void skipUntilSpace();
1013 Value& currentValue();
1016 getLocationLineAndColumn(Location location,
int& line,
int& column)
const;
1017 JSONCPP_STRING getLocationLineAndColumn(Location location)
const;
1019 void skipCommentTokens(Token& token);
1021 typedef std::stack<Value*> Nodes;
1028 Location lastValueEnd_;
1033 OurFeatures
const features_;
1034 bool collectComments_;
1039 OurReader::OurReader(OurFeatures
const& features)
1040 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1041 lastValue_(), commentsBefore_(),
1043 features_(features), collectComments_() {
1046 bool OurReader::parse(
const char* beginDoc,
1049 bool collectComments) {
1050 if (!features_.allowComments_) {
1051 collectComments =
false;
1056 collectComments_ = collectComments;
1060 commentsBefore_ =
"";
1062 while (!nodes_.empty())
1067 bool successful = readValue();
1069 skipCommentTokens(token);
1070 if (features_.failIfExtra_) {
1071 if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
1072 addError(
"Extra non-whitespace after JSON value.", token);
1076 if (collectComments_ && !commentsBefore_.empty())
1078 if (features_.strictRoot_) {
1079 if (!root.isArray() && !root.isObject()) {
1082 token.type_ = tokenError;
1083 token.start_ = beginDoc;
1084 token.end_ = endDoc;
1086 "A valid JSON document must be either an array or an object value.",
1094 bool OurReader::readValue() {
1095 if (stackDepth_ >= features_.stackLimit_) throwRuntimeError(
"Exceeded stackLimit in readValue().");
1098 skipCommentTokens(token);
1099 bool successful =
true;
1101 if (collectComments_ && !commentsBefore_.empty()) {
1103 commentsBefore_ =
"";
1106 switch (token.type_) {
1107 case tokenObjectBegin:
1108 successful = readObject(token);
1109 currentValue().setOffsetLimit(current_ - begin_);
1111 case tokenArrayBegin:
1112 successful = readArray(token);
1113 currentValue().setOffsetLimit(current_ - begin_);
1116 successful = decodeNumber(token);
1119 successful = decodeString(token);
1124 currentValue().swapPayload(v);
1125 currentValue().setOffsetStart(token.start_ - begin_);
1126 currentValue().setOffsetLimit(token.end_ - begin_);
1132 currentValue().swapPayload(v);
1133 currentValue().setOffsetStart(token.start_ - begin_);
1134 currentValue().setOffsetLimit(token.end_ - begin_);
1140 currentValue().swapPayload(v);
1141 currentValue().setOffsetStart(token.start_ - begin_);
1142 currentValue().setOffsetLimit(token.end_ - begin_);
1147 Value v(std::numeric_limits<double>::quiet_NaN());
1148 currentValue().swapPayload(v);
1149 currentValue().setOffsetStart(token.start_ - begin_);
1150 currentValue().setOffsetLimit(token.end_ - begin_);
1155 Value v(std::numeric_limits<double>::infinity());
1156 currentValue().swapPayload(v);
1157 currentValue().setOffsetStart(token.start_ - begin_);
1158 currentValue().setOffsetLimit(token.end_ - begin_);
1163 Value v(-std::numeric_limits<double>::infinity());
1164 currentValue().swapPayload(v);
1165 currentValue().setOffsetStart(token.start_ - begin_);
1166 currentValue().setOffsetLimit(token.end_ - begin_);
1169 case tokenArraySeparator:
1170 case tokenObjectEnd:
1172 if (features_.allowDroppedNullPlaceholders_) {
1177 currentValue().swapPayload(v);
1178 currentValue().setOffsetStart(current_ - begin_ - 1);
1179 currentValue().setOffsetLimit(current_ - begin_);
1183 currentValue().setOffsetStart(token.start_ - begin_);
1184 currentValue().setOffsetLimit(token.end_ - begin_);
1185 return addError(
"Syntax error: value, object or array expected.", token);
1188 if (collectComments_) {
1189 lastValueEnd_ = current_;
1190 lastValue_ = ¤tValue();
1197 void OurReader::skipCommentTokens(Token& token) {
1198 if (features_.allowComments_) {
1201 }
while (token.type_ == tokenComment);
1207 bool OurReader::readToken(Token& token) {
1209 token.start_ = current_;
1210 Char c = getNextChar();
1214 token.type_ = tokenObjectBegin;
1217 token.type_ = tokenObjectEnd;
1220 token.type_ = tokenArrayBegin;
1223 token.type_ = tokenArrayEnd;
1226 token.type_ = tokenString;
1230 if (features_.allowSingleQuotes_) {
1231 token.type_ = tokenString;
1232 ok = readStringSingleQuote();
1236 token.type_ = tokenComment;
1249 token.type_ = tokenNumber;
1253 if (readNumber(
true)) {
1254 token.type_ = tokenNumber;
1256 token.type_ = tokenNegInf;
1257 ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
1261 token.type_ = tokenTrue;
1262 ok = match(
"rue", 3);
1265 token.type_ = tokenFalse;
1266 ok = match(
"alse", 4);
1269 token.type_ = tokenNull;
1270 ok = match(
"ull", 3);
1273 if (features_.allowSpecialFloats_) {
1274 token.type_ = tokenNaN;
1275 ok = match(
"aN", 2);
1281 if (features_.allowSpecialFloats_) {
1282 token.type_ = tokenPosInf;
1283 ok = match(
"nfinity", 7);
1289 token.type_ = tokenArraySeparator;
1292 token.type_ = tokenMemberSeparator;
1295 token.type_ = tokenEndOfStream;
1302 token.type_ = tokenError;
1303 token.end_ = current_;
1307 void OurReader::skipSpaces() {
1308 while (current_ != end_) {
1310 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
1317 bool OurReader::match(Location pattern,
int patternLength) {
1318 if (end_ - current_ < patternLength)
1320 int index = patternLength;
1322 if (current_[index] != pattern[index])
1324 current_ += patternLength;
1328 bool OurReader::readComment() {
1329 Location commentBegin = current_ - 1;
1330 Char c = getNextChar();
1331 bool successful =
false;
1333 successful = readCStyleComment();
1335 successful = readCppStyleComment();
1339 if (collectComments_) {
1346 addComment(commentBegin, current_, placement);
1352 OurReader::addComment(Location begin, Location end,
CommentPlacement placement) {
1353 assert(collectComments_);
1356 assert(lastValue_ != 0);
1357 lastValue_->setComment(normalized, placement);
1359 commentsBefore_ += normalized;
1363 bool OurReader::readCStyleComment() {
1364 while (current_ != end_) {
1365 Char c = getNextChar();
1366 if (c ==
'*' && *current_ ==
'/')
1369 return getNextChar() ==
'/';
1372 bool OurReader::readCppStyleComment() {
1373 while (current_ != end_) {
1374 Char c = getNextChar();
1379 if (current_ != end_ && *current_ ==
'\n')
1388 bool OurReader::readNumber(
bool checkInf) {
1389 const char *p = current_;
1390 if (checkInf && p != end_ && *p ==
'I') {
1396 while (c >=
'0' && c <=
'9')
1397 c = (current_ = p) < end_ ? *p++ :
'\0';
1400 c = (current_ = p) < end_ ? *p++ :
'\0';
1401 while (c >=
'0' && c <=
'9')
1402 c = (current_ = p) < end_ ? *p++ :
'\0';
1405 if (c ==
'e' || c ==
'E') {
1406 c = (current_ = p) < end_ ? *p++ :
'\0';
1407 if (c ==
'+' || c ==
'-')
1408 c = (current_ = p) < end_ ? *p++ :
'\0';
1409 while (c >=
'0' && c <=
'9')
1410 c = (current_ = p) < end_ ? *p++ :
'\0';
1414 bool OurReader::readString() {
1416 while (current_ != end_) {
1427 bool OurReader::readStringSingleQuote() {
1429 while (current_ != end_) {
1439 bool OurReader::readObject(Token& tokenStart) {
1443 currentValue().swapPayload(init);
1444 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1445 while (readToken(tokenName)) {
1446 bool initialTokenOk =
true;
1447 while (tokenName.type_ == tokenComment && initialTokenOk)
1448 initialTokenOk = readToken(tokenName);
1449 if (!initialTokenOk)
1451 if (tokenName.type_ == tokenObjectEnd && name.empty())
1454 if (tokenName.type_ == tokenString) {
1455 if (!decodeString(tokenName, name))
1456 return recoverFromError(tokenObjectEnd);
1457 }
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
1459 if (!decodeNumber(tokenName, numberName))
1460 return recoverFromError(tokenObjectEnd);
1461 name = numberName.asString();
1467 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
1468 return addErrorAndRecover(
1469 "Missing ':' after object member name", colon, tokenObjectEnd);
1471 if (name.length() >= (1U<<30)) throwRuntimeError(
"keylength >= 2^30");
1472 if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
1474 return addErrorAndRecover(
1475 msg, tokenName, tokenObjectEnd);
1477 Value& value = currentValue()[name];
1478 nodes_.push(&value);
1479 bool ok = readValue();
1482 return recoverFromError(tokenObjectEnd);
1485 if (!readToken(comma) ||
1486 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1487 comma.type_ != tokenComment)) {
1488 return addErrorAndRecover(
1489 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1491 bool finalizeTokenOk =
true;
1492 while (comma.type_ == tokenComment && finalizeTokenOk)
1493 finalizeTokenOk = readToken(comma);
1494 if (comma.type_ == tokenObjectEnd)
1497 return addErrorAndRecover(
1498 "Missing '}' or object member name", tokenName, tokenObjectEnd);
1501 bool OurReader::readArray(Token& tokenStart) {
1503 currentValue().swapPayload(init);
1504 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1506 if (*current_ ==
']')
1509 readToken(endArray);
1514 Value& value = currentValue()[index++];
1515 nodes_.push(&value);
1516 bool ok = readValue();
1519 return recoverFromError(tokenArrayEnd);
1523 ok = readToken(token);
1524 while (token.type_ == tokenComment && ok) {
1525 ok = readToken(token);
1528 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1529 if (!ok || badTokenType) {
1530 return addErrorAndRecover(
1531 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1533 if (token.type_ == tokenArrayEnd)
1539 bool OurReader::decodeNumber(Token& token) {
1541 if (!decodeNumber(token, decoded))
1543 currentValue().swapPayload(decoded);
1544 currentValue().setOffsetStart(token.start_ - begin_);
1545 currentValue().setOffsetLimit(token.end_ - begin_);
1549 bool OurReader::decodeNumber(Token& token, Value& decoded) {
1553 Location current = token.start_;
1554 bool isNegative = *current ==
'-';
1560 : Value::maxLargestUInt;
1563 while (current < token.end_) {
1564 Char c = *current++;
1565 if (c < '0' || c >
'9')
1566 return decodeDouble(token, decoded);
1568 if (value >= threshold) {
1573 if (value > threshold || current != token.end_ ||
1574 digit > maxIntegerValue % 10) {
1575 return decodeDouble(token, decoded);
1578 value = value * 10 + digit;
1589 bool OurReader::decodeDouble(Token& token) {
1591 if (!decodeDouble(token, decoded))
1593 currentValue().swapPayload(decoded);
1594 currentValue().setOffsetStart(token.start_ - begin_);
1595 currentValue().setOffsetLimit(token.end_ - begin_);
1599 bool OurReader::decodeDouble(Token& token, Value& decoded) {
1601 const int bufferSize = 32;
1603 ptrdiff_t
const length = token.end_ - token.start_;
1607 return addError(
"Unable to parse token length", token);
1609 size_t const ulength =
static_cast<size_t>(length);
1616 char format[] =
"%lf";
1618 if (length <= bufferSize) {
1619 Char buffer[bufferSize + 1];
1620 memcpy(buffer, token.start_, ulength);
1622 count = sscanf(buffer, format, &value);
1625 count = sscanf(buffer.c_str(), format, &value);
1630 "' is not a number.",
1636 bool OurReader::decodeString(Token& token) {
1638 if (!decodeString(token, decoded_string))
1640 Value decoded(decoded_string);
1641 currentValue().swapPayload(decoded);
1642 currentValue().setOffsetStart(token.start_ - begin_);
1643 currentValue().setOffsetLimit(token.end_ - begin_);
1647 bool OurReader::decodeString(Token& token,
JSONCPP_STRING& decoded) {
1648 decoded.reserve(
static_cast<size_t>(token.end_ - token.start_ - 2));
1649 Location current = token.start_ + 1;
1650 Location end = token.end_ - 1;
1651 while (current != end) {
1652 Char c = *current++;
1655 else if (c ==
'\\') {
1657 return addError(
"Empty escape sequence in string", token, current);
1658 Char escape = *current++;
1685 unsigned int unicode;
1686 if (!decodeUnicodeCodePoint(token, current, end, unicode))
1691 return addError(
"Bad escape sequence in string", token, current);
1700 bool OurReader::decodeUnicodeCodePoint(Token& token,
1703 unsigned int& unicode) {
1705 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
1707 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
1709 if (end - current < 6)
1711 "additional six characters expected to parse unicode surrogate pair.",
1714 unsigned int surrogatePair;
1715 if (*(current++) ==
'\\' && *(current++) ==
'u') {
1716 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
1717 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1721 return addError(
"expecting another \\u token to begin the second half of "
1722 "a unicode surrogate pair",
1729 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
1732 unsigned int& ret_unicode) {
1733 if (end - current < 4)
1735 "Bad unicode escape sequence in string: four digits expected.",
1739 for (
int index = 0; index < 4; ++index) {
1740 Char c = *current++;
1742 if (c >=
'0' && c <=
'9')
1744 else if (c >=
'a' && c <=
'f')
1745 unicode += c -
'a' + 10;
1746 else if (c >=
'A' && c <=
'F')
1747 unicode += c -
'A' + 10;
1750 "Bad unicode escape sequence in string: hexadecimal digit expected.",
1754 ret_unicode =
static_cast<unsigned int>(unicode);
1759 OurReader::addError(
const JSONCPP_STRING& message, Token& token, Location extra) {
1761 info.token_ = token;
1762 info.message_ = message;
1763 info.extra_ = extra;
1764 errors_.push_back(info);
1768 bool OurReader::recoverFromError(TokenType skipUntilToken) {
1769 size_t errorCount = errors_.size();
1772 if (!readToken(skip))
1773 errors_.resize(errorCount);
1774 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
1777 errors_.resize(errorCount);
1781 bool OurReader::addErrorAndRecover(
const JSONCPP_STRING& message,
1783 TokenType skipUntilToken) {
1784 addError(message, token);
1785 return recoverFromError(skipUntilToken);
1788 Value& OurReader::currentValue() {
return *(nodes_.top()); }
1790 OurReader::Char OurReader::getNextChar() {
1791 if (current_ == end_)
1796 void OurReader::getLocationLineAndColumn(Location location,
1798 int& column)
const {
1799 Location current = begin_;
1800 Location lastLineStart = current;
1802 while (current < location && current != end_) {
1803 Char c = *current++;
1805 if (*current ==
'\n')
1807 lastLineStart = current;
1809 }
else if (c ==
'\n') {
1810 lastLineStart = current;
1815 column = int(location - lastLineStart) + 1;
1819 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location)
const {
1821 getLocationLineAndColumn(location, line, column);
1822 char buffer[18 + 16 + 16 + 1];
1823 snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
1829 for (Errors::const_iterator itError = errors_.begin();
1830 itError != errors_.end();
1832 const ErrorInfo& error = *itError;
1834 "* " + getLocationLineAndColumn(error.token_.start_) +
"\n";
1835 formattedMessage +=
" " + error.message_ +
"\n";
1838 "See " + getLocationLineAndColumn(error.extra_) +
" for detail.\n";
1840 return formattedMessage;
1843 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
const {
1844 std::vector<OurReader::StructuredError> allErrors;
1845 for (Errors::const_iterator itError = errors_.begin();
1846 itError != errors_.end();
1848 const ErrorInfo& error = *itError;
1849 OurReader::StructuredError structured;
1850 structured.offset_start = error.token_.start_ - begin_;
1851 structured.offset_limit = error.token_.end_ - begin_;
1852 structured.message = error.message_;
1853 allErrors.push_back(structured);
1858 bool OurReader::pushError(
const Value& value,
const JSONCPP_STRING& message) {
1859 ptrdiff_t length = end_ - begin_;
1860 if(value.getOffsetStart() > length
1861 || value.getOffsetLimit() > length)
1864 token.type_ = tokenError;
1865 token.start_ = begin_ + value.getOffsetStart();
1866 token.end_ = end_ + value.getOffsetLimit();
1868 info.token_ = token;
1869 info.message_ = message;
1871 errors_.push_back(info);
1875 bool OurReader::pushError(
const Value& value,
const JSONCPP_STRING& message,
const Value& extra) {
1876 ptrdiff_t length = end_ - begin_;
1877 if(value.getOffsetStart() > length
1878 || value.getOffsetLimit() > length
1879 || extra.getOffsetLimit() > length)
1882 token.type_ = tokenError;
1883 token.start_ = begin_ + value.getOffsetStart();
1884 token.end_ = begin_ + value.getOffsetLimit();
1886 info.token_ = token;
1887 info.message_ = message;
1888 info.extra_ = begin_ + extra.getOffsetStart();
1889 errors_.push_back(info);
1893 bool OurReader::good()
const {
1894 return !errors_.size();
1898 class OurCharReader :
public CharReader {
1899 bool const collectComments_;
1903 bool collectComments,
1904 OurFeatures
const& features)
1905 : collectComments_(collectComments)
1909 char const* beginDoc,
char const* endDoc,
1911 bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
1913 *errs = reader_.getFormattedErrorMessages();
1928 OurFeatures features = OurFeatures::all();
1931 features.allowDroppedNullPlaceholders_ =
settings_[
"allowDroppedNullPlaceholders"].
asBool();
1933 features.allowSingleQuotes_ =
settings_[
"allowSingleQuotes"].
asBool();
1937 features.allowSpecialFloats_ =
settings_[
"allowSpecialFloats"].
asBool();
1938 return new OurCharReader(collectComments, features);
1942 valid_keys->clear();
1943 valid_keys->insert(
"collectComments");
1944 valid_keys->insert(
"allowComments");
1945 valid_keys->insert(
"strictRoot");
1946 valid_keys->insert(
"allowDroppedNullPlaceholders");
1947 valid_keys->insert(
"allowNumericKeys");
1948 valid_keys->insert(
"allowSingleQuotes");
1949 valid_keys->insert(
"stackLimit");
1950 valid_keys->insert(
"failIfExtra");
1951 valid_keys->insert(
"rejectDupKeys");
1952 valid_keys->insert(
"allowSpecialFloats");
1957 if (!invalid) invalid = &my_invalid;
1959 std::set<JSONCPP_STRING> valid_keys;
1962 size_t n = keys.size();
1963 for (
size_t i = 0; i < n; ++i) {
1965 if (valid_keys.find(key) == valid_keys.end()) {
1969 return 0u == inv.
size();
1979 (*settings)[
"allowComments"] =
false;
1980 (*settings)[
"strictRoot"] =
true;
1981 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
1982 (*settings)[
"allowNumericKeys"] =
false;
1983 (*settings)[
"allowSingleQuotes"] =
false;
1984 (*settings)[
"stackLimit"] = 1000;
1985 (*settings)[
"failIfExtra"] =
true;
1986 (*settings)[
"rejectDupKeys"] =
true;
1987 (*settings)[
"allowSpecialFloats"] =
false;
1994 (*settings)[
"collectComments"] =
true;
1995 (*settings)[
"allowComments"] =
true;
1996 (*settings)[
"strictRoot"] =
false;
1997 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
1998 (*settings)[
"allowNumericKeys"] =
false;
1999 (*settings)[
"allowSingleQuotes"] =
false;
2000 (*settings)[
"stackLimit"] = 1000;
2001 (*settings)[
"failIfExtra"] =
false;
2002 (*settings)[
"rejectDupKeys"] =
false;
2003 (*settings)[
"allowSpecialFloats"] =
false;
2015 ssin << sin.rdbuf();
2017 char const* begin = doc.data();
2018 char const* end = begin + doc.size();
2021 return reader->parse(begin, end, root, errs);
2030 "Error from reader: %s",
2033 throwRuntimeError(errs);