6 #if !defined(JSON_IS_AMALGAMATION)
11 #endif // if !defined(JSON_IS_AMALGAMATION)
18 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
20 #pragma warning(disable : 4996)
29 : allowComments_(true), strictRoot_(false),
30 allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
51 return c == c1 || c == c2 || c == c3 || c == c4;
60 return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
64 for (; begin < end; ++begin)
65 if (*begin ==
'\n' || *begin ==
'\r')
74 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
75 lastValue_(), commentsBefore_(), features_(
Features::all()),
79 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
80 lastValue_(), commentsBefore_(), features_(features), collectComments_() {
86 const char *begin = document_.c_str();
87 const char *end = begin + document_.length();
88 return parse(begin, end, root, collectComments);
100 std::getline(sin, doc, (
char)EOF);
101 return parse(doc, root, collectComments);
107 bool collectComments) {
109 collectComments =
false;
114 collectComments_ = collectComments;
118 commentsBefore_ =
"";
120 while (!nodes_.empty())
124 bool successful = readValue();
126 skipCommentTokens(token);
127 if (collectComments_ && !commentsBefore_.empty())
133 token.type_ = tokenError;
134 token.start_ = beginDoc;
137 "A valid JSON document must be either an array or an object value.",
145 bool Reader::readValue() {
147 skipCommentTokens(token);
148 bool successful =
true;
150 if (collectComments_ && !commentsBefore_.empty()) {
152 size_t lastNonNewline = commentsBefore_.find_last_not_of(
"\r\n");
153 if (lastNonNewline != std::string::npos) {
154 commentsBefore_.erase(lastNonNewline + 1);
156 commentsBefore_.clear();
160 commentsBefore_ =
"";
163 switch (token.type_) {
164 case tokenObjectBegin:
165 successful = readObject(token);
168 case tokenArrayBegin:
169 successful = readArray(token);
173 successful = decodeNumber(token);
176 successful = decodeString(token);
179 currentValue() =
true;
184 currentValue() =
false;
189 currentValue() = Value();
193 case tokenArraySeparator:
198 currentValue() = Value();
207 return addError(
"Syntax error: value, object or array expected.", token);
210 if (collectComments_) {
211 lastValueEnd_ = current_;
212 lastValue_ = ¤tValue();
218 void Reader::skipCommentTokens(Token &token) {
222 }
while (token.type_ == tokenComment);
228 bool Reader::expectToken(TokenType type, Token &token,
const char *message) {
230 if (token.type_ != type)
231 return addError(message, token);
235 bool Reader::readToken(Token &token) {
237 token.start_ = current_;
238 Char c = getNextChar();
242 token.type_ = tokenObjectBegin;
245 token.type_ = tokenObjectEnd;
248 token.type_ = tokenArrayBegin;
251 token.type_ = tokenArrayEnd;
254 token.type_ = tokenString;
258 token.type_ = tokenComment;
272 token.type_ = tokenNumber;
276 token.type_ = tokenTrue;
277 ok = match(
"rue", 3);
280 token.type_ = tokenFalse;
281 ok = match(
"alse", 4);
284 token.type_ = tokenNull;
285 ok = match(
"ull", 3);
288 token.type_ = tokenArraySeparator;
291 token.type_ = tokenMemberSeparator;
294 token.type_ = tokenEndOfStream;
301 token.type_ = tokenError;
302 token.end_ = current_;
306 void Reader::skipSpaces() {
307 while (current_ != end_) {
309 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
316 bool Reader::match(Location pattern,
int patternLength) {
317 if (end_ - current_ < patternLength)
319 int index = patternLength;
321 if (current_[index] != pattern[index])
323 current_ += patternLength;
327 bool Reader::readComment() {
328 Location commentBegin = current_ - 1;
329 Char c = getNextChar();
330 bool successful =
false;
332 successful = readCStyleComment();
334 successful = readCppStyleComment();
338 if (collectComments_) {
345 addComment(commentBegin, current_, placement);
351 Reader::addComment(Location begin, Location end,
CommentPlacement placement) {
352 assert(collectComments_);
354 assert(lastValue_ != 0);
355 lastValue_->
setComment(std::string(begin, end), placement);
357 if (!commentsBefore_.empty())
358 commentsBefore_ +=
"\n";
359 commentsBefore_ += std::string(begin, end);
363 bool Reader::readCStyleComment() {
364 while (current_ != end_) {
365 Char c = getNextChar();
366 if (c ==
'*' && *current_ ==
'/')
369 return getNextChar() ==
'/';
372 bool Reader::readCppStyleComment() {
373 while (current_ != end_) {
374 Char c = getNextChar();
375 if (c ==
'\r' || c ==
'\n')
381 void Reader::readNumber() {
382 while (current_ != end_) {
383 if (!(*current_ >=
'0' && *current_ <=
'9') &&
384 !
in(*current_,
'.',
'e',
'E',
'+',
'-'))
390 bool Reader::readString() {
392 while (current_ != end_) {
402 bool Reader::readObject(Token &tokenStart) {
407 while (readToken(tokenName)) {
408 bool initialTokenOk =
true;
409 while (tokenName.type_ == tokenComment && initialTokenOk)
410 initialTokenOk = readToken(tokenName);
413 if (tokenName.type_ == tokenObjectEnd && name.empty())
416 if (tokenName.type_ == tokenString) {
417 if (!decodeString(tokenName, name))
418 return recoverFromError(tokenObjectEnd);
421 if (!decodeNumber(tokenName, numberName))
422 return recoverFromError(tokenObjectEnd);
423 name = numberName.asString();
429 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
430 return addErrorAndRecover(
431 "Missing ':' after object member name", colon, tokenObjectEnd);
433 Value &value = currentValue()[name];
435 bool ok = readValue();
438 return recoverFromError(tokenObjectEnd);
441 if (!readToken(comma) ||
442 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
443 comma.type_ != tokenComment)) {
444 return addErrorAndRecover(
445 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
447 bool finalizeTokenOk =
true;
448 while (comma.type_ == tokenComment && finalizeTokenOk)
449 finalizeTokenOk = readToken(comma);
450 if (comma.type_ == tokenObjectEnd)
453 return addErrorAndRecover(
454 "Missing '}' or object member name", tokenName, tokenObjectEnd);
457 bool Reader::readArray(Token &tokenStart) {
461 if (*current_ ==
']')
469 Value &value = currentValue()[index++];
471 bool ok = readValue();
474 return recoverFromError(tokenArrayEnd);
478 ok = readToken(token);
479 while (token.type_ == tokenComment && ok) {
480 ok = readToken(token);
483 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
484 if (!ok || badTokenType) {
485 return addErrorAndRecover(
486 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
488 if (token.type_ == tokenArrayEnd)
494 bool Reader::decodeNumber(Token &token) {
496 if (!decodeNumber(token, decoded))
498 currentValue() = decoded;
504 bool Reader::decodeNumber(Token &token, Value &decoded) {
505 bool isDouble =
false;
506 for (
Location inspect = token.start_; inspect != token.end_; ++inspect) {
507 isDouble = isDouble ||
in(*inspect,
'.',
'e',
'E',
'+') ||
508 (*inspect ==
'-' && inspect != token.start_);
511 return decodeDouble(token, decoded);
516 bool isNegative = *current ==
'-';
521 : Value::maxLargestUInt;
524 while (current < token.end_) {
526 if (c < '0' || c >
'9')
527 return addError(
"'" + std::string(token.start_, token.end_) +
528 "' is not a number.",
531 if (value >= threshold) {
536 if (value > threshold || current != token.end_ ||
537 digit > maxIntegerValue % 10) {
538 return decodeDouble(token, decoded);
541 value = value * 10 + digit;
552 bool Reader::decodeDouble(Token &token) {
554 if (!decodeDouble(token, decoded))
556 currentValue() = decoded;
562 bool Reader::decodeDouble(Token &token, Value &decoded) {
564 const int bufferSize = 32;
566 int length = int(token.end_ - token.start_);
570 return addError(
"Unable to parse token length", token);
578 char format[] =
"%lf";
580 if (length <= bufferSize) {
581 Char buffer[bufferSize + 1];
582 memcpy(buffer, token.start_, length);
584 count = sscanf(buffer, format, &value);
586 std::string buffer(token.start_, token.end_);
587 count = sscanf(buffer.c_str(), format, &value);
591 return addError(
"'" + std::string(token.start_, token.end_) +
592 "' is not a number.",
598 bool Reader::decodeString(Token &token) {
600 if (!decodeString(token, decoded))
602 currentValue() = decoded;
608 bool Reader::decodeString(Token &token, std::string &decoded) {
609 decoded.reserve(token.end_ - token.start_ - 2);
610 Location current = token.start_ + 1;
612 while (current != end) {
616 else if (c ==
'\\') {
618 return addError(
"Empty escape sequence in string", token, current);
619 Char escape = *current++;
646 unsigned int unicode;
647 if (!decodeUnicodeCodePoint(token, current, end, unicode))
652 return addError(
"Bad escape sequence in string", token, current);
661 bool Reader::decodeUnicodeCodePoint(Token &token,
664 unsigned int &unicode) {
666 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
668 if (unicode >= 0xD800 && unicode <= 0xDBFF) {
670 if (end - current < 6)
672 "additional six characters expected to parse unicode surrogate pair.",
675 unsigned int surrogatePair;
676 if (*(current++) ==
'\\' && *(current++) ==
'u') {
677 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
678 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
682 return addError(
"expecting another \\u token to begin the second half of "
683 "a unicode surrogate pair",
690 bool Reader::decodeUnicodeEscapeSequence(Token &token,
693 unsigned int &unicode) {
694 if (end - current < 4)
696 "Bad unicode escape sequence in string: four digits expected.",
700 for (
int index = 0; index < 4; ++index) {
703 if (c >=
'0' && c <=
'9')
705 else if (c >=
'a' && c <=
'f')
706 unicode += c -
'a' + 10;
707 else if (c >=
'A' && c <=
'F')
708 unicode += c -
'A' + 10;
711 "Bad unicode escape sequence in string: hexadecimal digit expected.",
719 Reader::addError(
const std::string &message, Token &token, Location extra) {
722 info.message_ = message;
724 errors_.push_back(info);
728 bool Reader::recoverFromError(TokenType skipUntilToken) {
729 int errorCount = int(errors_.size());
732 if (!readToken(skip))
733 errors_.resize(errorCount);
734 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
737 errors_.resize(errorCount);
741 bool Reader::addErrorAndRecover(
const std::string &message,
743 TokenType skipUntilToken) {
744 addError(message, token);
745 return recoverFromError(skipUntilToken);
748 Value &Reader::currentValue() {
return *(nodes_.top()); }
751 if (current_ == end_)
756 void Reader::getLocationLineAndColumn(Location location,
762 while (current < location && current != end_) {
765 if (*current ==
'\n')
767 lastLineStart = current;
769 }
else if (c ==
'\n') {
770 lastLineStart = current;
775 column = int(location - lastLineStart) + 1;
779 std::string Reader::getLocationLineAndColumn(Location location)
const {
781 getLocationLineAndColumn(location, line, column);
782 char buffer[18 + 16 + 16 + 1];
783 #if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
785 _snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
787 sprintf_s(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
790 snprintf(buffer,
sizeof(buffer),
"Line %d, Column %d", line, column);
801 std::string formattedMessage;
802 for (Errors::const_iterator itError = errors_.begin();
803 itError != errors_.end();
805 const ErrorInfo &error = *itError;
807 "* " + getLocationLineAndColumn(error.token_.start_) +
"\n";
808 formattedMessage +=
" " + error.message_ +
"\n";
811 "See " + getLocationLineAndColumn(error.extra_) +
" for detail.\n";
813 return formattedMessage;
817 std::vector<Reader::StructuredError> allErrors;
818 for (Errors::const_iterator itError = errors_.begin();
819 itError != errors_.end();
821 const ErrorInfo &error = *itError;
825 structured.
message = error.message_;
826 allErrors.push_back(structured);
833 bool ok = reader.
parse(sin, root,
true);
836 "Error from reader: %s",