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 #define snprintf std::snprintf
36 #if defined(__QNXNTO__)
37 #define sscanf std::sscanf
40 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
42 #pragma warning(disable : 4996)
50 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
60 : allowComments_(true), strictRoot_(false),
61 allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
78 for (; begin < end; ++begin)
79 if (*begin ==
'\n' || *begin ==
'\r')
88 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
89 lastValue_(), commentsBefore_(), features_(
Features::all()),
93 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
94 lastValue_(), commentsBefore_(), features_(features), collectComments_() {
100 const char* begin = document_.c_str();
101 const char* end = begin + document_.length();
102 return parse(begin, end, root, collectComments);
114 std::getline(sin, doc, (
char)EOF);
115 return parse(doc, root, collectComments);
121 bool collectComments) {
123 collectComments =
false;
128 collectComments_ = collectComments;
132 commentsBefore_ =
"";
134 while (!nodes_.empty())
139 bool successful = readValue();
141 skipCommentTokens(token);
142 if (collectComments_ && !commentsBefore_.empty())
148 token.type_ = tokenError;
149 token.start_ = beginDoc;
152 "A valid JSON document must be either an array or an object value.",
160 bool Reader::readValue() {
169 skipCommentTokens(token);
170 bool successful =
true;
172 if (collectComments_ && !commentsBefore_.empty()) {
174 commentsBefore_ =
"";
177 switch (token.type_) {
178 case tokenObjectBegin:
179 successful = readObject(token);
182 case tokenArrayBegin:
183 successful = readArray(token);
187 successful = decodeNumber(token);
190 successful = decodeString(token);
216 case tokenArraySeparator:
232 return addError(
"Syntax error: value, object or array expected.", token);
235 if (collectComments_) {
236 lastValueEnd_ = current_;
237 lastValue_ = ¤tValue();
244 void Reader::skipCommentTokens(Token& token) {
248 }
while (token.type_ == tokenComment);
254 bool Reader::readToken(Token& token) {
256 token.start_ = current_;
257 Char c = getNextChar();
261 token.type_ = tokenObjectBegin;
264 token.type_ = tokenObjectEnd;
267 token.type_ = tokenArrayBegin;
270 token.type_ = tokenArrayEnd;
273 token.type_ = tokenString;
277 token.type_ = tokenComment;
291 token.type_ = tokenNumber;
295 token.type_ = tokenTrue;
296 ok = match(
"rue", 3);
299 token.type_ = tokenFalse;
300 ok = match(
"alse", 4);
303 token.type_ = tokenNull;
304 ok = match(
"ull", 3);
307 token.type_ = tokenArraySeparator;
310 token.type_ = tokenMemberSeparator;
313 token.type_ = tokenEndOfStream;
320 token.type_ = tokenError;
321 token.end_ = current_;
325 void Reader::skipSpaces() {
326 while (current_ != end_) {
328 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
335 bool Reader::match(Location pattern,
int patternLength) {
336 if (end_ - current_ < patternLength)
338 int index = patternLength;
340 if (current_[index] != pattern[index])
342 current_ += patternLength;
346 bool Reader::readComment() {
347 Location commentBegin = current_ - 1;
348 Char c = getNextChar();
349 bool successful =
false;
351 successful = readCStyleComment();
353 successful = readCppStyleComment();
357 if (collectComments_) {
364 addComment(commentBegin, current_, placement);
370 std::string normalized;
371 normalized.reserve(end - begin);
373 while (current != end) {
376 if (current != end && *current ==
'\n')
389 Reader::addComment(Location begin, Location end,
CommentPlacement placement) {
390 assert(collectComments_);
391 const std::string& normalized =
normalizeEOL(begin, end);
393 assert(lastValue_ != 0);
394 lastValue_->
setComment(normalized, placement);
396 commentsBefore_ += normalized;
400 bool Reader::readCStyleComment() {
401 while (current_ != end_) {
402 Char c = getNextChar();
403 if (c ==
'*' && *current_ ==
'/')
406 return getNextChar() ==
'/';
409 bool Reader::readCppStyleComment() {
410 while (current_ != end_) {
411 Char c = getNextChar();
416 if (current_ != end_ && *current_ ==
'\n')
425 void Reader::readNumber() {
426 const char *p = current_;
429 while (c >=
'0' && c <=
'9')
430 c = (current_ = p) < end_ ? *p++ : 0;
433 c = (current_ = p) < end_ ? *p++ : 0;
434 while (c >=
'0' && c <=
'9')
435 c = (current_ = p) < end_ ? *p++ : 0;
438 if (c ==
'e' || c ==
'E') {
439 c = (current_ = p) < end_ ? *p++ : 0;
440 if (c ==
'+' || c ==
'-')
441 c = (current_ = p) < end_ ? *p++ : 0;
442 while (c >=
'0' && c <=
'9')
443 c = (current_ = p) < end_ ? *p++ : 0;
447 bool Reader::readString() {
449 while (current_ != end_) {
459 bool Reader::readObject(Token& tokenStart) {
465 while (readToken(tokenName)) {
466 bool initialTokenOk =
true;
467 while (tokenName.type_ == tokenComment && initialTokenOk)
468 initialTokenOk = readToken(tokenName);
471 if (tokenName.type_ == tokenObjectEnd && name.empty())
474 if (tokenName.type_ == tokenString) {
475 if (!decodeString(tokenName, name))
476 return recoverFromError(tokenObjectEnd);
479 if (!decodeNumber(tokenName, numberName))
480 return recoverFromError(tokenObjectEnd);
481 name = numberName.asString();
487 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
488 return addErrorAndRecover(
489 "Missing ':' after object member name", colon, tokenObjectEnd);
491 Value& value = currentValue()[name];
493 bool ok = readValue();
496 return recoverFromError(tokenObjectEnd);
499 if (!readToken(comma) ||
500 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
501 comma.type_ != tokenComment)) {
502 return addErrorAndRecover(
503 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
505 bool finalizeTokenOk =
true;
506 while (comma.type_ == tokenComment && finalizeTokenOk)
507 finalizeTokenOk = readToken(comma);
508 if (comma.type_ == tokenObjectEnd)
511 return addErrorAndRecover(
512 "Missing '}' or object member name", tokenName, tokenObjectEnd);
515 bool Reader::readArray(Token& tokenStart) {
520 if (*current_ ==
']')
528 Value& value = currentValue()[index++];
530 bool ok = readValue();
533 return recoverFromError(tokenArrayEnd);
537 ok = readToken(token);
538 while (token.type_ == tokenComment && ok) {
539 ok = readToken(token);
542 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
543 if (!ok || badTokenType) {
544 return addErrorAndRecover(
545 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
547 if (token.type_ == tokenArrayEnd)
553 bool Reader::decodeNumber(Token& token) {
555 if (!decodeNumber(token, decoded))
563 bool Reader::decodeNumber(Token& token, Value& decoded) {
568 bool isNegative = *current ==
'-';
577 while (current < token.end_) {
579 if (c < '0' || c >
'9')
580 return decodeDouble(token, decoded);
582 if (value >= threshold) {
587 if (value > threshold || current != token.end_ ||
588 digit > maxIntegerValue % 10) {
589 return decodeDouble(token, decoded);
592 value = value * 10 + digit;
594 if (isNegative && value == maxIntegerValue)
605 bool Reader::decodeDouble(Token& token) {
607 if (!decodeDouble(token, decoded))
615 bool Reader::decodeDouble(Token& token, Value& decoded) {
617 std::string buffer(token.start_, token.end_);
618 std::istringstream is(buffer);
620 return addError(
"'" + std::string(token.start_, token.end_) +
621 "' is not a number.",
627 bool Reader::decodeString(Token& token) {
628 std::string decoded_string;
629 if (!decodeString(token, decoded_string))
631 Value decoded(decoded_string);
638 bool Reader::decodeString(Token& token, std::string& decoded) {
639 decoded.reserve(token.end_ - token.start_ - 2);
640 Location current = token.start_ + 1;
642 while (current != end) {
646 else if (c ==
'\\') {
648 return addError(
"Empty escape sequence in string", token, current);
649 Char escape = *current++;
676 unsigned int unicode;
677 if (!decodeUnicodeCodePoint(token, current, end, unicode))
682 return addError(
"Bad escape sequence in string", token, current);
691 bool Reader::decodeUnicodeCodePoint(Token& token,
694 unsigned int& unicode) {
696 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
698 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
700 if (end - current < 6)
702 "additional six characters expected to parse unicode surrogate pair.",
705 unsigned int surrogatePair;
706 if (*(current++) ==
'\\' && *(current++) ==
'u') {
707 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
708 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
712 return addError(
"expecting another \\u token to begin the second half of "
713 "a unicode surrogate pair",
720 bool Reader::decodeUnicodeEscapeSequence(Token& token,
723 unsigned int& unicode) {
724 if (end - current < 4)
726 "Bad unicode escape sequence in string: four digits expected.",
730 for (
int index = 0; index < 4; ++index) {
733 if (c >=
'0' && c <=
'9')
735 else if (c >=
'a' && c <=
'f')
736 unicode += c -
'a' + 10;
737 else if (c >=
'A' && c <=
'F')
738 unicode += c -
'A' + 10;
741 "Bad unicode escape sequence in string: hexadecimal digit expected.",
749 Reader::addError(
const std::string& message, Token& token, Location extra) {
752 info.message_ = message;
754 errors_.push_back(info);
758 bool Reader::recoverFromError(TokenType skipUntilToken) {
759 int errorCount = int(errors_.size());
762 if (!readToken(skip))
763 errors_.resize(errorCount);
764 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
767 errors_.resize(errorCount);
771 bool Reader::addErrorAndRecover(
const std::string& message,
773 TokenType skipUntilToken) {
774 addError(message, token);
775 return recoverFromError(skipUntilToken);
778 Value& Reader::currentValue() {
return *(nodes_.top()); }
781 if (current_ == end_)
786 void Reader::getLocationLineAndColumn(Location location,
792 while (current < location && current != end_) {
795 if (*current ==
'\n')
797 lastLineStart = current;
799 }
else if (c ==
'\n') {
800 lastLineStart = current;
805 column = int(location - lastLineStart) + 1;
809 std::string Reader::getLocationLineAndColumn(Location location)
const {
811 getLocationLineAndColumn(location, line, column);
812 char buffer[18 + 16 + 16 + 1];
813 snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
823 std::string formattedMessage;
824 for (Errors::const_iterator itError = errors_.begin();
825 itError != errors_.end();
827 const ErrorInfo& error = *itError;
829 "* " + getLocationLineAndColumn(error.token_.start_) +
"\n";
830 formattedMessage +=
" " + error.message_ +
"\n";
833 "See " + getLocationLineAndColumn(error.extra_) +
" for detail.\n";
835 return formattedMessage;
839 std::vector<Reader::StructuredError> allErrors;
840 for (Errors::const_iterator itError = errors_.begin();
841 itError != errors_.end();
843 const ErrorInfo& error = *itError;
847 structured.
message = error.message_;
848 allErrors.push_back(structured);
854 size_t length = end_ - begin_;
859 token.type_ = tokenError;
864 info.message_ = message;
866 errors_.push_back(info);
871 size_t length = end_ - begin_;
877 token.type_ = tokenError;
882 info.message_ = message;
884 errors_.push_back(info);
889 return !errors_.size();
895 static OurFeatures all();
898 bool allowDroppedNullPlaceholders_;
899 bool allowNumericKeys_;
900 bool allowSingleQuotes_;
903 bool allowSpecialFloats_;
910 OurFeatures OurFeatures::all() {
return OurFeatures(); }
919 typedef const Char* Location;
920 struct StructuredError {
926 OurReader(OurFeatures
const& features);
927 bool parse(
const char* beginDoc,
930 bool collectComments =
true);
931 std::string getFormattedErrorMessages()
const;
932 std::vector<StructuredError> getStructuredErrors()
const;
933 bool pushError(
const Value& value,
const std::string& message);
934 bool pushError(
const Value& value,
const std::string& message,
const Value& extra);
938 OurReader(OurReader
const&);
939 void operator=(OurReader
const&);
942 tokenEndOfStream = 0,
956 tokenMemberSeparator,
971 std::string message_;
975 typedef std::deque<ErrorInfo> Errors;
977 bool readToken(Token& token);
979 bool match(Location pattern,
int patternLength);
981 bool readCStyleComment();
982 bool readCppStyleComment();
984 bool readStringSingleQuote();
985 bool readNumber(
bool checkInf);
987 bool readObject(Token& token);
988 bool readArray(Token& token);
989 bool decodeNumber(Token& token);
990 bool decodeNumber(Token& token, Value& decoded);
991 bool decodeString(Token& token);
992 bool decodeString(Token& token, std::string& decoded);
993 bool decodeDouble(Token& token);
994 bool decodeDouble(Token& token, Value& decoded);
995 bool decodeUnicodeCodePoint(Token& token,
998 unsigned int& unicode);
999 bool decodeUnicodeEscapeSequence(Token& token,
1002 unsigned int& unicode);
1003 bool addError(
const std::string& message, Token& token, Location extra = 0);
1004 bool recoverFromError(TokenType skipUntilToken);
1005 bool addErrorAndRecover(
const std::string& message,
1007 TokenType skipUntilToken);
1008 void skipUntilSpace();
1009 Value& currentValue();
1012 getLocationLineAndColumn(Location location,
int& line,
int& column)
const;
1013 std::string getLocationLineAndColumn(Location location)
const;
1015 void skipCommentTokens(Token& token);
1017 typedef std::stack<Value*> Nodes;
1020 std::string document_;
1024 Location lastValueEnd_;
1026 std::string commentsBefore_;
1029 OurFeatures
const features_;
1030 bool collectComments_;
1035 OurReader::OurReader(OurFeatures
const& features)
1036 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1037 lastValue_(), commentsBefore_(),
1039 features_(features), collectComments_() {
1042 bool OurReader::parse(
const char* beginDoc,
1045 bool collectComments) {
1046 if (!features_.allowComments_) {
1047 collectComments =
false;
1052 collectComments_ = collectComments;
1056 commentsBefore_ =
"";
1058 while (!nodes_.empty())
1063 bool successful = readValue();
1065 skipCommentTokens(token);
1066 if (features_.failIfExtra_) {
1067 if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
1068 addError(
"Extra non-whitespace after JSON value.", token);
1072 if (collectComments_ && !commentsBefore_.empty())
1074 if (features_.strictRoot_) {
1075 if (!root.isArray() && !root.isObject()) {
1078 token.type_ = tokenError;
1079 token.start_ = beginDoc;
1080 token.end_ = endDoc;
1082 "A valid JSON document must be either an array or an object value.",
1090 bool OurReader::readValue() {
1091 if (stackDepth_ >= features_.stackLimit_)
throwRuntimeError(
"Exceeded stackLimit in readValue().");
1094 skipCommentTokens(token);
1095 bool successful =
true;
1097 if (collectComments_ && !commentsBefore_.empty()) {
1099 commentsBefore_ =
"";
1102 switch (token.type_) {
1103 case tokenObjectBegin:
1104 successful = readObject(token);
1105 currentValue().setOffsetLimit(current_ - begin_);
1107 case tokenArrayBegin:
1108 successful = readArray(token);
1109 currentValue().setOffsetLimit(current_ - begin_);
1112 successful = decodeNumber(token);
1115 successful = decodeString(token);
1120 currentValue().swapPayload(v);
1121 currentValue().setOffsetStart(token.start_ - begin_);
1122 currentValue().setOffsetLimit(token.end_ - begin_);
1128 currentValue().swapPayload(v);
1129 currentValue().setOffsetStart(token.start_ - begin_);
1130 currentValue().setOffsetLimit(token.end_ - begin_);
1136 currentValue().swapPayload(v);
1137 currentValue().setOffsetStart(token.start_ - begin_);
1138 currentValue().setOffsetLimit(token.end_ - begin_);
1143 Value v(std::numeric_limits<double>::quiet_NaN());
1144 currentValue().swapPayload(v);
1145 currentValue().setOffsetStart(token.start_ - begin_);
1146 currentValue().setOffsetLimit(token.end_ - begin_);
1151 Value v(std::numeric_limits<double>::infinity());
1152 currentValue().swapPayload(v);
1153 currentValue().setOffsetStart(token.start_ - begin_);
1154 currentValue().setOffsetLimit(token.end_ - begin_);
1159 Value v(-std::numeric_limits<double>::infinity());
1160 currentValue().swapPayload(v);
1161 currentValue().setOffsetStart(token.start_ - begin_);
1162 currentValue().setOffsetLimit(token.end_ - begin_);
1165 case tokenArraySeparator:
1166 case tokenObjectEnd:
1168 if (features_.allowDroppedNullPlaceholders_) {
1173 currentValue().swapPayload(v);
1174 currentValue().setOffsetStart(current_ - begin_ - 1);
1175 currentValue().setOffsetLimit(current_ - begin_);
1179 currentValue().setOffsetStart(token.start_ - begin_);
1180 currentValue().setOffsetLimit(token.end_ - begin_);
1181 return addError(
"Syntax error: value, object or array expected.", token);
1184 if (collectComments_) {
1185 lastValueEnd_ = current_;
1186 lastValue_ = ¤tValue();
1193 void OurReader::skipCommentTokens(Token& token) {
1194 if (features_.allowComments_) {
1197 }
while (token.type_ == tokenComment);
1203 bool OurReader::readToken(Token& token) {
1205 token.start_ = current_;
1206 Char c = getNextChar();
1210 token.type_ = tokenObjectBegin;
1213 token.type_ = tokenObjectEnd;
1216 token.type_ = tokenArrayBegin;
1219 token.type_ = tokenArrayEnd;
1222 token.type_ = tokenString;
1226 if (features_.allowSingleQuotes_) {
1227 token.type_ = tokenString;
1228 ok = readStringSingleQuote();
1232 token.type_ = tokenComment;
1245 token.type_ = tokenNumber;
1249 if (readNumber(
true)) {
1250 token.type_ = tokenNumber;
1252 token.type_ = tokenNegInf;
1253 ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
1257 token.type_ = tokenTrue;
1258 ok = match(
"rue", 3);
1261 token.type_ = tokenFalse;
1262 ok = match(
"alse", 4);
1265 token.type_ = tokenNull;
1266 ok = match(
"ull", 3);
1269 if (features_.allowSpecialFloats_) {
1270 token.type_ = tokenNaN;
1271 ok = match(
"aN", 2);
1277 if (features_.allowSpecialFloats_) {
1278 token.type_ = tokenPosInf;
1279 ok = match(
"nfinity", 7);
1285 token.type_ = tokenArraySeparator;
1288 token.type_ = tokenMemberSeparator;
1291 token.type_ = tokenEndOfStream;
1298 token.type_ = tokenError;
1299 token.end_ = current_;
1303 void OurReader::skipSpaces() {
1304 while (current_ != end_) {
1306 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
1313 bool OurReader::match(Location pattern,
int patternLength) {
1314 if (end_ - current_ < patternLength)
1316 int index = patternLength;
1318 if (current_[index] != pattern[index])
1320 current_ += patternLength;
1324 bool OurReader::readComment() {
1325 Location commentBegin = current_ - 1;
1326 Char c = getNextChar();
1327 bool successful =
false;
1329 successful = readCStyleComment();
1331 successful = readCppStyleComment();
1335 if (collectComments_) {
1342 addComment(commentBegin, current_, placement);
1348 OurReader::addComment(Location begin, Location end,
CommentPlacement placement) {
1349 assert(collectComments_);
1350 const std::string& normalized =
normalizeEOL(begin, end);
1352 assert(lastValue_ != 0);
1353 lastValue_->setComment(normalized, placement);
1355 commentsBefore_ += normalized;
1359 bool OurReader::readCStyleComment() {
1360 while (current_ != end_) {
1361 Char c = getNextChar();
1362 if (c ==
'*' && *current_ ==
'/')
1365 return getNextChar() ==
'/';
1368 bool OurReader::readCppStyleComment() {
1369 while (current_ != end_) {
1370 Char c = getNextChar();
1375 if (current_ != end_ && *current_ ==
'\n')
1384 bool OurReader::readNumber(
bool checkInf) {
1385 const char *p = current_;
1386 if (checkInf && p != end_ && *p ==
'I') {
1392 while (c >=
'0' && c <=
'9')
1393 c = (current_ = p) < end_ ? *p++ : 0;
1396 c = (current_ = p) < end_ ? *p++ : 0;
1397 while (c >=
'0' && c <=
'9')
1398 c = (current_ = p) < end_ ? *p++ : 0;
1401 if (c ==
'e' || c ==
'E') {
1402 c = (current_ = p) < end_ ? *p++ : 0;
1403 if (c ==
'+' || c ==
'-')
1404 c = (current_ = p) < end_ ? *p++ : 0;
1405 while (c >=
'0' && c <=
'9')
1406 c = (current_ = p) < end_ ? *p++ : 0;
1410 bool OurReader::readString() {
1412 while (current_ != end_) {
1423 bool OurReader::readStringSingleQuote() {
1425 while (current_ != end_) {
1435 bool OurReader::readObject(Token& tokenStart) {
1439 currentValue().swapPayload(init);
1440 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1441 while (readToken(tokenName)) {
1442 bool initialTokenOk =
true;
1443 while (tokenName.type_ == tokenComment && initialTokenOk)
1444 initialTokenOk = readToken(tokenName);
1445 if (!initialTokenOk)
1447 if (tokenName.type_ == tokenObjectEnd && name.empty())
1450 if (tokenName.type_ == tokenString) {
1451 if (!decodeString(tokenName, name))
1452 return recoverFromError(tokenObjectEnd);
1453 }
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
1455 if (!decodeNumber(tokenName, numberName))
1456 return recoverFromError(tokenObjectEnd);
1457 name = numberName.asString();
1463 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
1464 return addErrorAndRecover(
1465 "Missing ':' after object member name", colon, tokenObjectEnd);
1468 if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
1469 std::string msg =
"Duplicate key: '" + name +
"'";
1470 return addErrorAndRecover(
1471 msg, tokenName, tokenObjectEnd);
1473 Value& value = currentValue()[name];
1474 nodes_.push(&value);
1475 bool ok = readValue();
1478 return recoverFromError(tokenObjectEnd);
1481 if (!readToken(comma) ||
1482 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1483 comma.type_ != tokenComment)) {
1484 return addErrorAndRecover(
1485 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1487 bool finalizeTokenOk =
true;
1488 while (comma.type_ == tokenComment && finalizeTokenOk)
1489 finalizeTokenOk = readToken(comma);
1490 if (comma.type_ == tokenObjectEnd)
1493 return addErrorAndRecover(
1494 "Missing '}' or object member name", tokenName, tokenObjectEnd);
1497 bool OurReader::readArray(Token& tokenStart) {
1499 currentValue().swapPayload(init);
1500 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1502 if (*current_ ==
']')
1505 readToken(endArray);
1510 Value& value = currentValue()[index++];
1511 nodes_.push(&value);
1512 bool ok = readValue();
1515 return recoverFromError(tokenArrayEnd);
1519 ok = readToken(token);
1520 while (token.type_ == tokenComment && ok) {
1521 ok = readToken(token);
1524 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1525 if (!ok || badTokenType) {
1526 return addErrorAndRecover(
1527 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1529 if (token.type_ == tokenArrayEnd)
1535 bool OurReader::decodeNumber(Token& token) {
1537 if (!decodeNumber(token, decoded))
1539 currentValue().swapPayload(decoded);
1540 currentValue().setOffsetStart(token.start_ - begin_);
1541 currentValue().setOffsetLimit(token.end_ - begin_);
1545 bool OurReader::decodeNumber(Token& token, Value& decoded) {
1549 Location current = token.start_;
1550 bool isNegative = *current ==
'-';
1556 : Value::maxLargestUInt;
1557 Value::LargestUInt threshold = maxIntegerValue / 10;
1558 Value::LargestUInt value = 0;
1559 while (current < token.end_) {
1560 Char c = *current++;
1561 if (c < '0' || c >
'9')
1562 return decodeDouble(token, decoded);
1564 if (value >= threshold) {
1569 if (value > threshold || current != token.end_ ||
1570 digit > maxIntegerValue % 10) {
1571 return decodeDouble(token, decoded);
1574 value = value * 10 + digit;
1585 bool OurReader::decodeDouble(Token& token) {
1587 if (!decodeDouble(token, decoded))
1589 currentValue().swapPayload(decoded);
1590 currentValue().setOffsetStart(token.start_ - begin_);
1591 currentValue().setOffsetLimit(token.end_ - begin_);
1595 bool OurReader::decodeDouble(Token& token, Value& decoded) {
1597 const int bufferSize = 32;
1599 int length = int(token.end_ - token.start_);
1603 return addError(
"Unable to parse token length", token);
1611 char format[] =
"%lf";
1613 if (length <= bufferSize) {
1614 Char buffer[bufferSize + 1];
1615 memcpy(buffer, token.start_, length);
1617 count = sscanf(buffer, format, &value);
1619 std::string buffer(token.start_, token.end_);
1620 count = sscanf(buffer.c_str(), format, &value);
1624 return addError(
"'" + std::string(token.start_, token.end_) +
1625 "' is not a number.",
1631 bool OurReader::decodeString(Token& token) {
1632 std::string decoded_string;
1633 if (!decodeString(token, decoded_string))
1635 Value decoded(decoded_string);
1636 currentValue().swapPayload(decoded);
1637 currentValue().setOffsetStart(token.start_ - begin_);
1638 currentValue().setOffsetLimit(token.end_ - begin_);
1642 bool OurReader::decodeString(Token& token, std::string& decoded) {
1643 decoded.reserve(token.end_ - token.start_ - 2);
1644 Location current = token.start_ + 1;
1645 Location end = token.end_ - 1;
1646 while (current != end) {
1647 Char c = *current++;
1650 else if (c ==
'\\') {
1652 return addError(
"Empty escape sequence in string", token, current);
1653 Char escape = *current++;
1680 unsigned int unicode;
1681 if (!decodeUnicodeCodePoint(token, current, end, unicode))
1686 return addError(
"Bad escape sequence in string", token, current);
1695 bool OurReader::decodeUnicodeCodePoint(Token& token,
1698 unsigned int& unicode) {
1700 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
1702 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
1704 if (end - current < 6)
1706 "additional six characters expected to parse unicode surrogate pair.",
1709 unsigned int surrogatePair;
1710 if (*(current++) ==
'\\' && *(current++) ==
'u') {
1711 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
1712 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1716 return addError(
"expecting another \\u token to begin the second half of "
1717 "a unicode surrogate pair",
1724 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
1727 unsigned int& unicode) {
1728 if (end - current < 4)
1730 "Bad unicode escape sequence in string: four digits expected.",
1734 for (
int index = 0; index < 4; ++index) {
1735 Char c = *current++;
1737 if (c >=
'0' && c <=
'9')
1739 else if (c >=
'a' && c <=
'f')
1740 unicode += c -
'a' + 10;
1741 else if (c >=
'A' && c <=
'F')
1742 unicode += c -
'A' + 10;
1745 "Bad unicode escape sequence in string: hexadecimal digit expected.",
1753 OurReader::addError(
const std::string& message, Token& token, Location extra) {
1755 info.token_ = token;
1756 info.message_ = message;
1757 info.extra_ = extra;
1758 errors_.push_back(info);
1762 bool OurReader::recoverFromError(TokenType skipUntilToken) {
1763 int errorCount = int(errors_.size());
1766 if (!readToken(skip))
1767 errors_.resize(errorCount);
1768 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
1771 errors_.resize(errorCount);
1775 bool OurReader::addErrorAndRecover(
const std::string& message,
1777 TokenType skipUntilToken) {
1778 addError(message, token);
1779 return recoverFromError(skipUntilToken);
1782 Value& OurReader::currentValue() {
return *(nodes_.top()); }
1784 OurReader::Char OurReader::getNextChar() {
1785 if (current_ == end_)
1790 void OurReader::getLocationLineAndColumn(Location location,
1792 int& column)
const {
1793 Location current = begin_;
1794 Location lastLineStart = current;
1796 while (current < location && current != end_) {
1797 Char c = *current++;
1799 if (*current ==
'\n')
1801 lastLineStart = current;
1803 }
else if (c ==
'\n') {
1804 lastLineStart = current;
1809 column = int(location - lastLineStart) + 1;
1813 std::string OurReader::getLocationLineAndColumn(Location location)
const {
1815 getLocationLineAndColumn(location, line, column);
1816 char buffer[18 + 16 + 16 + 1];
1817 snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
1821 std::string OurReader::getFormattedErrorMessages()
const {
1822 std::string formattedMessage;
1823 for (Errors::const_iterator itError = errors_.begin();
1824 itError != errors_.end();
1826 const ErrorInfo& error = *itError;
1828 "* " + getLocationLineAndColumn(error.token_.start_) +
"\n";
1829 formattedMessage +=
" " + error.message_ +
"\n";
1832 "See " + getLocationLineAndColumn(error.extra_) +
" for detail.\n";
1834 return formattedMessage;
1837 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
const {
1838 std::vector<OurReader::StructuredError> allErrors;
1839 for (Errors::const_iterator itError = errors_.begin();
1840 itError != errors_.end();
1842 const ErrorInfo& error = *itError;
1843 OurReader::StructuredError structured;
1844 structured.offset_start = error.token_.start_ - begin_;
1845 structured.offset_limit = error.token_.end_ - begin_;
1846 structured.message = error.message_;
1847 allErrors.push_back(structured);
1852 bool OurReader::pushError(
const Value& value,
const std::string& message) {
1853 size_t length = end_ - begin_;
1854 if(value.getOffsetStart() > length
1855 || value.getOffsetLimit() > length)
1858 token.type_ = tokenError;
1859 token.start_ = begin_ + value.getOffsetStart();
1860 token.end_ = end_ + value.getOffsetLimit();
1862 info.token_ = token;
1863 info.message_ = message;
1865 errors_.push_back(info);
1869 bool OurReader::pushError(
const Value& value,
const std::string& message,
const Value& extra) {
1870 size_t length = end_ - begin_;
1871 if(value.getOffsetStart() > length
1872 || value.getOffsetLimit() > length
1873 || extra.getOffsetLimit() > length)
1876 token.type_ = tokenError;
1877 token.start_ = begin_ + value.getOffsetStart();
1878 token.end_ = begin_ + value.getOffsetLimit();
1880 info.token_ = token;
1881 info.message_ = message;
1882 info.extra_ = begin_ + extra.getOffsetStart();
1883 errors_.push_back(info);
1887 bool OurReader::good()
const {
1888 return !errors_.size();
1892 class OurCharReader :
public CharReader {
1893 bool const collectComments_;
1897 bool collectComments,
1898 OurFeatures
const& features)
1899 : collectComments_(collectComments)
1903 char const* beginDoc,
char const* endDoc,
1904 Value* root, std::string* errs)
override {
1905 bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
1907 *errs = reader_.getFormattedErrorMessages();
1922 OurFeatures features = OurFeatures::all();
1925 features.allowDroppedNullPlaceholders_ =
settings_[
"allowDroppedNullPlaceholders"].
asBool();
1927 features.allowSingleQuotes_ =
settings_[
"allowSingleQuotes"].
asBool();
1931 features.allowSpecialFloats_ =
settings_[
"allowSpecialFloats"].
asBool();
1932 return new OurCharReader(collectComments, features);
1936 valid_keys->clear();
1937 valid_keys->insert(
"collectComments");
1938 valid_keys->insert(
"allowComments");
1939 valid_keys->insert(
"strictRoot");
1940 valid_keys->insert(
"allowDroppedNullPlaceholders");
1941 valid_keys->insert(
"allowNumericKeys");
1942 valid_keys->insert(
"allowSingleQuotes");
1943 valid_keys->insert(
"stackLimit");
1944 valid_keys->insert(
"failIfExtra");
1945 valid_keys->insert(
"rejectDupKeys");
1946 valid_keys->insert(
"allowSpecialFloats");
1951 if (!invalid) invalid = &my_invalid;
1953 std::set<std::string> valid_keys;
1956 size_t n = keys.size();
1957 for (
size_t i = 0; i < n; ++i) {
1958 std::string
const& key = keys[i];
1959 if (valid_keys.find(key) == valid_keys.end()) {
1963 return 0u == inv.
size();
1973 (*settings)[
"allowComments"] =
false;
1974 (*settings)[
"strictRoot"] =
true;
1975 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
1976 (*settings)[
"allowNumericKeys"] =
false;
1977 (*settings)[
"allowSingleQuotes"] =
false;
1978 (*settings)[
"stackLimit"] = 1000;
1979 (*settings)[
"failIfExtra"] =
true;
1980 (*settings)[
"rejectDupKeys"] =
true;
1981 (*settings)[
"allowSpecialFloats"] =
false;
1988 (*settings)[
"collectComments"] =
true;
1989 (*settings)[
"allowComments"] =
true;
1990 (*settings)[
"strictRoot"] =
false;
1991 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
1992 (*settings)[
"allowNumericKeys"] =
false;
1993 (*settings)[
"allowSingleQuotes"] =
false;
1994 (*settings)[
"stackLimit"] = 1000;
1995 (*settings)[
"failIfExtra"] =
false;
1996 (*settings)[
"rejectDupKeys"] =
false;
1997 (*settings)[
"allowSpecialFloats"] =
false;
2006 Value* root, std::string* errs)
2008 std::ostringstream ssin;
2009 ssin << sin.rdbuf();
2010 std::string doc = ssin.str();
2011 char const* begin = doc.data();
2012 char const* end = begin + doc.size();
2015 return reader->parse(begin, end, root, errs);
2024 "Error from reader: %s",