7 #if !defined(JSON_IS_AMALGAMATION) 
   12 #endif // if !defined(JSON_IS_AMALGAMATION) 
   24 #if __cplusplus >= 201103L 
   27 #define sscanf std::sscanf 
   33 #if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) 
   34 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 
   35 #endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 
   40 #pragma warning(disable : 4996) 
   45 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) 
   46 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000 
   54 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 
   79 bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
 
   80   for (; begin < end; ++begin)
 
   81     if (*begin == 
'\n' || *begin == 
'\r')
 
   89 Reader::Reader() : features_(Features::all()) {}
 
   91 Reader::Reader(
const Features& features) : features_(features) {}
 
   93 bool Reader::parse(
const std::string& document, Value& root,
 
   94                    bool collectComments) {
 
   95   document_.assign(document.begin(), document.end());
 
   96   const char* begin = document_.c_str();
 
   97   const char* end = begin + document_.length();
 
   98   return parse(begin, end, root, collectComments);
 
  101 bool Reader::parse(std::istream& is, Value& root, 
bool collectComments) {
 
  110   std::getline(is, doc, 
static_cast<char> EOF);
 
  111   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
 
  114 bool Reader::parse(
const char* beginDoc, 
const char* endDoc, Value& root,
 
  115                    bool collectComments) {
 
  116   if (!features_.allowComments_) {
 
  117     collectComments = 
false;
 
  122   collectComments_ = collectComments;
 
  124   lastValueEnd_ = 
nullptr;
 
  125   lastValue_ = 
nullptr;
 
  126   commentsBefore_.clear();
 
  128   while (!nodes_.empty())
 
  132   bool successful = readValue();
 
  134   skipCommentTokens(token);
 
  135   if (collectComments_ && !commentsBefore_.empty())
 
  137   if (features_.strictRoot_) {
 
  138     if (!root.isArray() && !root.isObject()) {
 
  141       token.type_ = tokenError;
 
  142       token.start_ = beginDoc;
 
  145           "A valid JSON document must be either an array or an object value.",
 
  153 bool Reader::readValue() {
 
  159     throwRuntimeError(
"Exceeded stackLimit in readValue().");
 
  162   skipCommentTokens(token);
 
  163   bool successful = 
true;
 
  165   if (collectComments_ && !commentsBefore_.empty()) {
 
  167     commentsBefore_.clear();
 
  170   switch (token.type_) {
 
  171   case tokenObjectBegin:
 
  172     successful = readObject(token);
 
  173     currentValue().setOffsetLimit(current_ - begin_);
 
  175   case tokenArrayBegin:
 
  176     successful = readArray(token);
 
  177     currentValue().setOffsetLimit(current_ - begin_);
 
  180     successful = decodeNumber(token);
 
  183     successful = decodeString(token);
 
  187     currentValue().swapPayload(v);
 
  188     currentValue().setOffsetStart(token.start_ - begin_);
 
  189     currentValue().setOffsetLimit(token.end_ - begin_);
 
  193     currentValue().swapPayload(v);
 
  194     currentValue().setOffsetStart(token.start_ - begin_);
 
  195     currentValue().setOffsetLimit(token.end_ - begin_);
 
  199     currentValue().swapPayload(v);
 
  200     currentValue().setOffsetStart(token.start_ - begin_);
 
  201     currentValue().setOffsetLimit(token.end_ - begin_);
 
  203   case tokenArraySeparator:
 
  206     if (features_.allowDroppedNullPlaceholders_) {
 
  211       currentValue().swapPayload(v);
 
  212       currentValue().setOffsetStart(current_ - begin_ - 1);
 
  213       currentValue().setOffsetLimit(current_ - begin_);
 
  217     currentValue().setOffsetStart(token.start_ - begin_);
 
  218     currentValue().setOffsetLimit(token.end_ - begin_);
 
  219     return addError(
"Syntax error: value, object or array expected.", token);
 
  222   if (collectComments_) {
 
  223     lastValueEnd_ = current_;
 
  224     lastValue_ = ¤tValue();
 
  230 void Reader::skipCommentTokens(Token& token) {
 
  231   if (features_.allowComments_) {
 
  234     } 
while (token.type_ == tokenComment);
 
  240 bool Reader::readToken(Token& token) {
 
  242   token.start_ = current_;
 
  243   Char c = getNextChar();
 
  247     token.type_ = tokenObjectBegin;
 
  250     token.type_ = tokenObjectEnd;
 
  253     token.type_ = tokenArrayBegin;
 
  256     token.type_ = tokenArrayEnd;
 
  259     token.type_ = tokenString;
 
  263     token.type_ = tokenComment;
 
  277     token.type_ = tokenNumber;
 
  281     token.type_ = tokenTrue;
 
  282     ok = match(
"rue", 3);
 
  285     token.type_ = tokenFalse;
 
  286     ok = match(
"alse", 4);
 
  289     token.type_ = tokenNull;
 
  290     ok = match(
"ull", 3);
 
  293     token.type_ = tokenArraySeparator;
 
  296     token.type_ = tokenMemberSeparator;
 
  299     token.type_ = tokenEndOfStream;
 
  306     token.type_ = tokenError;
 
  307   token.end_ = current_;
 
  311 void Reader::skipSpaces() {
 
  312   while (current_ != end_) {
 
  314     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
 
  321 bool Reader::match(
const Char* pattern, 
int patternLength) {
 
  322   if (end_ - current_ < patternLength)
 
  324   int index = patternLength;
 
  326     if (current_[index] != pattern[index])
 
  328   current_ += patternLength;
 
  332 bool Reader::readComment() {
 
  333   Location commentBegin = current_ - 1;
 
  334   Char c = getNextChar();
 
  335   bool successful = 
false;
 
  337     successful = readCStyleComment();
 
  339     successful = readCppStyleComment();
 
  343   if (collectComments_) {
 
  345     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
 
  346       if (c != 
'*' || !containsNewLine(commentBegin, current_))
 
  350     addComment(commentBegin, current_, placement);
 
  355 String Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
 
  357   normalized.reserve(
static_cast<size_t>(end - begin));
 
  358   Reader::Location current = begin;
 
  359   while (current != end) {
 
  362       if (current != end && *current == 
'\n')
 
  374 void Reader::addComment(Location begin, Location end,
 
  376   assert(collectComments_);
 
  377   const String& normalized = normalizeEOL(begin, end);
 
  379     assert(lastValue_ != 
nullptr);
 
  380     lastValue_->setComment(normalized, placement);
 
  382     commentsBefore_ += normalized;
 
  386 bool Reader::readCStyleComment() {
 
  387   while ((current_ + 1) < end_) {
 
  388     Char c = getNextChar();
 
  389     if (c == 
'*' && *current_ == 
'/')
 
  392   return getNextChar() == 
'/';
 
  395 bool Reader::readCppStyleComment() {
 
  396   while (current_ != end_) {
 
  397     Char c = getNextChar();
 
  402       if (current_ != end_ && *current_ == 
'\n')
 
  411 void Reader::readNumber() {
 
  412   Location p = current_;
 
  415   while (c >= 
'0' && c <= 
'9')
 
  416     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  419     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  420     while (c >= 
'0' && c <= 
'9')
 
  421       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  424   if (c == 
'e' || c == 
'E') {
 
  425     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  426     if (c == 
'+' || c == 
'-')
 
  427       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  428     while (c >= 
'0' && c <= 
'9')
 
  429       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  433 bool Reader::readString() {
 
  435   while (current_ != end_) {
 
  445 bool Reader::readObject(Token& token) {
 
  449   currentValue().swapPayload(init);
 
  450   currentValue().setOffsetStart(token.start_ - begin_);
 
  451   while (readToken(tokenName)) {
 
  452     bool initialTokenOk = 
true;
 
  453     while (tokenName.type_ == tokenComment && initialTokenOk)
 
  454       initialTokenOk = readToken(tokenName);
 
  457     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
 
  460     if (tokenName.type_ == tokenString) {
 
  461       if (!decodeString(tokenName, name))
 
  462         return recoverFromError(tokenObjectEnd);
 
  463     } 
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
 
  465       if (!decodeNumber(tokenName, numberName))
 
  466         return recoverFromError(tokenObjectEnd);
 
  467       name = 
String(numberName.asCString());
 
  473     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
 
  474       return addErrorAndRecover(
"Missing ':' after object member name", colon,
 
  477     Value& value = currentValue()[name];
 
  479     bool ok = readValue();
 
  482       return recoverFromError(tokenObjectEnd);
 
  485     if (!readToken(comma) ||
 
  486         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
 
  487          comma.type_ != tokenComment)) {
 
  488       return addErrorAndRecover(
"Missing ',' or '}' in object declaration",
 
  489                                 comma, tokenObjectEnd);
 
  491     bool finalizeTokenOk = 
true;
 
  492     while (comma.type_ == tokenComment && finalizeTokenOk)
 
  493       finalizeTokenOk = readToken(comma);
 
  494     if (comma.type_ == tokenObjectEnd)
 
  497   return addErrorAndRecover(
"Missing '}' or object member name", tokenName,
 
  501 bool Reader::readArray(Token& token) {
 
  503   currentValue().swapPayload(init);
 
  504   currentValue().setOffsetStart(token.start_ - begin_);
 
  506   if (current_ != end_ && *current_ == 
']') 
 
  514     Value& value = currentValue()[index++];
 
  516     bool ok = readValue();
 
  519       return recoverFromError(tokenArrayEnd);
 
  523     ok = readToken(currentToken);
 
  524     while (currentToken.type_ == tokenComment && ok) {
 
  525       ok = readToken(currentToken);
 
  527     bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
 
  528                          currentToken.type_ != tokenArrayEnd);
 
  529     if (!ok || badTokenType) {
 
  530       return addErrorAndRecover(
"Missing ',' or ']' in array declaration",
 
  531                                 currentToken, tokenArrayEnd);
 
  533     if (currentToken.type_ == tokenArrayEnd)
 
  539 bool Reader::decodeNumber(Token& token) {
 
  541   if (!decodeNumber(token, decoded))
 
  543   currentValue().swapPayload(decoded);
 
  544   currentValue().setOffsetStart(token.start_ - begin_);
 
  545   currentValue().setOffsetLimit(token.end_ - begin_);
 
  549 bool Reader::decodeNumber(Token& token, Value& decoded) {
 
  553   Location current = token.start_;
 
  554   bool isNegative = *current == 
'-';
 
  564   while (current < token.end_) {
 
  566     if (c < '0' || c > 
'9')
 
  567       return decodeDouble(token, decoded);
 
  569     if (value >= threshold) {
 
  574       if (value > threshold || current != token.end_ ||
 
  575           digit > maxIntegerValue % 10) {
 
  576         return decodeDouble(token, decoded);
 
  579     value = value * 10 + digit;
 
  581   if (isNegative && value == maxIntegerValue)
 
  592 bool Reader::decodeDouble(Token& token) {
 
  594   if (!decodeDouble(token, decoded))
 
  596   currentValue().swapPayload(decoded);
 
  597   currentValue().setOffsetStart(token.start_ - begin_);
 
  598   currentValue().setOffsetLimit(token.end_ - begin_);
 
  602 bool Reader::decodeDouble(Token& token, Value& decoded) {
 
  604   String buffer(token.start_, token.end_);
 
  608         "'" + 
String(token.start_, token.end_) + 
"' is not a number.", token);
 
  613 bool Reader::decodeString(Token& token) {
 
  615   if (!decodeString(token, decoded_string))
 
  617   Value decoded(decoded_string);
 
  618   currentValue().swapPayload(decoded);
 
  619   currentValue().setOffsetStart(token.start_ - begin_);
 
  620   currentValue().setOffsetLimit(token.end_ - begin_);
 
  624 bool Reader::decodeString(Token& token, 
String& decoded) {
 
  625   decoded.reserve(
static_cast<size_t>(token.end_ - token.start_ - 2));
 
  626   Location current = token.start_ + 1; 
 
  627   Location end = token.end_ - 1;       
 
  628   while (current != end) {
 
  632     else if (c == 
'\\') {
 
  634         return addError(
"Empty escape sequence in string", token, current);
 
  635       Char escape = *current++;
 
  662         unsigned int unicode;
 
  663         if (!decodeUnicodeCodePoint(token, current, end, unicode))
 
  668         return addError(
"Bad escape sequence in string", token, current);
 
  677 bool Reader::decodeUnicodeCodePoint(Token& token, Location& current,
 
  678                                     Location end, 
unsigned int& unicode) {
 
  680   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
 
  682   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
 
  684     if (end - current < 6)
 
  686           "additional six characters expected to parse unicode surrogate pair.",
 
  688     if (*(current++) == 
'\\' && *(current++) == 
'u') {
 
  689       unsigned int surrogatePair;
 
  690       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
 
  691         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
 
  695       return addError(
"expecting another \\u token to begin the second half of " 
  696                       "a unicode surrogate pair",
 
  702 bool Reader::decodeUnicodeEscapeSequence(Token& token, Location& current,
 
  704                                          unsigned int& ret_unicode) {
 
  705   if (end - current < 4)
 
  707         "Bad unicode escape sequence in string: four digits expected.", token,
 
  710   for (
int index = 0; index < 4; ++index) {
 
  713     if (c >= 
'0' && c <= 
'9')
 
  715     else if (c >= 
'a' && c <= 
'f')
 
  716       unicode += c - 
'a' + 10;
 
  717     else if (c >= 
'A' && c <= 
'F')
 
  718       unicode += c - 
'A' + 10;
 
  721           "Bad unicode escape sequence in string: hexadecimal digit expected.",
 
  724   ret_unicode = 
static_cast<unsigned int>(unicode);
 
  728 bool Reader::addError(
const String& message, Token& token, Location extra) {
 
  731   info.message_ = message;
 
  733   errors_.push_back(info);
 
  737 bool Reader::recoverFromError(TokenType skipUntilToken) {
 
  738   size_t const errorCount = errors_.size();
 
  741     if (!readToken(skip))
 
  742       errors_.resize(errorCount); 
 
  743     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
 
  746   errors_.resize(errorCount);
 
  750 bool Reader::addErrorAndRecover(
const String& message, Token& token,
 
  751                                 TokenType skipUntilToken) {
 
  752   addError(message, token);
 
  753   return recoverFromError(skipUntilToken);
 
  756 Value& Reader::currentValue() { 
return *(nodes_.top()); }
 
  758 Reader::Char Reader::getNextChar() {
 
  759   if (current_ == end_)
 
  764 void Reader::getLocationLineAndColumn(Location location, 
int& line,
 
  766   Location current = begin_;
 
  767   Location lastLineStart = current;
 
  769   while (current < location && current != end_) {
 
  772       if (*current == 
'\n')
 
  774       lastLineStart = current;
 
  776     } 
else if (c == 
'\n') {
 
  777       lastLineStart = current;
 
  782   column = int(location - lastLineStart) + 1;
 
  786 String Reader::getLocationLineAndColumn(Location location)
 const {
 
  788   getLocationLineAndColumn(location, line, column);
 
  789   char buffer[18 + 16 + 16 + 1];
 
  790   jsoncpp_snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
 
  795 String Reader::getFormatedErrorMessages()
 const {
 
  796   return getFormattedErrorMessages();
 
  799 String Reader::getFormattedErrorMessages()
 const {
 
  801   for (
const auto& error : errors_) {
 
  803         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
 
  804     formattedMessage += 
"  " + error.message_ + 
"\n";
 
  807           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
 
  809   return formattedMessage;
 
  812 std::vector<Reader::StructuredError> Reader::getStructuredErrors()
 const {
 
  813   std::vector<Reader::StructuredError> allErrors;
 
  814   for (
const auto& error : errors_) {
 
  815     Reader::StructuredError structured;
 
  816     structured.offset_start = error.token_.start_ - begin_;
 
  817     structured.offset_limit = error.token_.end_ - begin_;
 
  818     structured.message = error.message_;
 
  819     allErrors.push_back(structured);
 
  824 bool Reader::pushError(
const Value& value, 
const String& message) {
 
  825   ptrdiff_t 
const length = end_ - begin_;
 
  826   if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
 
  829   token.type_ = tokenError;
 
  830   token.start_ = begin_ + value.getOffsetStart();
 
  831   token.end_ = begin_ + value.getOffsetLimit();
 
  834   info.message_ = message;
 
  835   info.extra_ = 
nullptr;
 
  836   errors_.push_back(info);
 
  840 bool Reader::pushError(
const Value& value, 
const String& message,
 
  841                        const Value& extra) {
 
  842   ptrdiff_t 
const length = end_ - begin_;
 
  843   if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
 
  844       extra.getOffsetLimit() > length)
 
  847   token.type_ = tokenError;
 
  848   token.start_ = begin_ + value.getOffsetStart();
 
  849   token.end_ = begin_ + value.getOffsetLimit();
 
  852   info.message_ = message;
 
  853   info.extra_ = begin_ + extra.getOffsetStart();
 
  854   errors_.push_back(info);
 
  858 bool Reader::good()
 const { 
return errors_.empty(); }
 
  864   static OurFeatures all();
 
  867   bool allowDroppedNullPlaceholders_;
 
  868   bool allowNumericKeys_;
 
  869   bool allowSingleQuotes_;
 
  872   bool allowSpecialFloats_;
 
  876 OurFeatures OurFeatures::all() { 
return {}; }
 
  886   using Location = 
const Char*;
 
  887   struct StructuredError {
 
  888     ptrdiff_t offset_start;
 
  889     ptrdiff_t offset_limit;
 
  893   explicit OurReader(OurFeatures 
const& features);
 
  894   bool parse(
const char* beginDoc, 
const char* endDoc, Value& root,
 
  895              bool collectComments = 
true);
 
  896   String getFormattedErrorMessages() 
const;
 
  897   std::vector<StructuredError> getStructuredErrors() 
const;
 
  900   OurReader(OurReader 
const&);      
 
  901   void operator=(OurReader 
const&); 
 
  904     tokenEndOfStream = 0,
 
  918     tokenMemberSeparator,
 
  937   using Errors = std::deque<ErrorInfo>;
 
  939   bool readToken(Token& token);
 
  941   bool match(
const Char* pattern, 
int patternLength);
 
  943   bool readCStyleComment(
bool* containsNewLineResult);
 
  944   bool readCppStyleComment();
 
  946   bool readStringSingleQuote();
 
  947   bool readNumber(
bool checkInf);
 
  949   bool readObject(Token& token);
 
  950   bool readArray(Token& token);
 
  951   bool decodeNumber(Token& token);
 
  952   bool decodeNumber(Token& token, Value& decoded);
 
  953   bool decodeString(Token& token);
 
  954   bool decodeString(Token& token, 
String& decoded);
 
  955   bool decodeDouble(Token& token);
 
  956   bool decodeDouble(Token& token, Value& decoded);
 
  957   bool decodeUnicodeCodePoint(Token& token, Location& current, Location end,
 
  958                               unsigned int& unicode);
 
  959   bool decodeUnicodeEscapeSequence(Token& token, Location& current,
 
  960                                    Location end, 
unsigned int& unicode);
 
  961   bool addError(
const String& message, Token& token, Location extra = 
nullptr);
 
  962   bool recoverFromError(TokenType skipUntilToken);
 
  963   bool addErrorAndRecover(
const String& message, Token& token,
 
  964                           TokenType skipUntilToken);
 
  965   void skipUntilSpace();
 
  966   Value& currentValue();
 
  968   void getLocationLineAndColumn(Location location, 
int& line,
 
  970   String getLocationLineAndColumn(Location location) 
const;
 
  972   void skipCommentTokens(Token& token);
 
  974   static String normalizeEOL(Location begin, Location end);
 
  975   static bool containsNewLine(Location begin, Location end);
 
  977   using Nodes = std::stack<Value*>;
 
  982   Location begin_ = 
nullptr;
 
  983   Location end_ = 
nullptr;
 
  984   Location current_ = 
nullptr;
 
  985   Location lastValueEnd_ = 
nullptr;
 
  986   Value* lastValue_ = 
nullptr;
 
  987   bool lastValueHasAComment_ = 
false;
 
  990   OurFeatures 
const features_;
 
  991   bool collectComments_ = 
false;
 
  996 bool OurReader::containsNewLine(OurReader::Location begin,
 
  997                                 OurReader::Location end) {
 
  998   for (; begin < end; ++begin)
 
  999     if (*begin == 
'\n' || *begin == 
'\r')
 
 1004 OurReader::OurReader(OurFeatures 
const& features) : features_(features) {}
 
 1006 bool OurReader::parse(
const char* beginDoc, 
const char* endDoc, Value& root,
 
 1007                       bool collectComments) {
 
 1008   if (!features_.allowComments_) {
 
 1009     collectComments = 
false;
 
 1014   collectComments_ = collectComments;
 
 1016   lastValueEnd_ = 
nullptr;
 
 1017   lastValue_ = 
nullptr;
 
 1018   commentsBefore_.clear();
 
 1020   while (!nodes_.empty())
 
 1024   bool successful = readValue();
 
 1027   skipCommentTokens(token);
 
 1028   if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
 
 1029     addError(
"Extra non-whitespace after JSON value.", token);
 
 1032   if (collectComments_ && !commentsBefore_.empty())
 
 1034   if (features_.strictRoot_) {
 
 1035     if (!root.isArray() && !root.isObject()) {
 
 1038       token.type_ = tokenError;
 
 1039       token.start_ = beginDoc;
 
 1040       token.end_ = endDoc;
 
 1042           "A valid JSON document must be either an array or an object value.",
 
 1050 bool OurReader::readValue() {
 
 1052   if (nodes_.size() > features_.stackLimit_)
 
 1053     throwRuntimeError(
"Exceeded stackLimit in readValue().");
 
 1055   skipCommentTokens(token);
 
 1056   bool successful = 
true;
 
 1058   if (collectComments_ && !commentsBefore_.empty()) {
 
 1060     commentsBefore_.clear();
 
 1063   switch (token.type_) {
 
 1064   case tokenObjectBegin:
 
 1065     successful = readObject(token);
 
 1066     currentValue().setOffsetLimit(current_ - begin_);
 
 1068   case tokenArrayBegin:
 
 1069     successful = readArray(token);
 
 1070     currentValue().setOffsetLimit(current_ - begin_);
 
 1073     successful = decodeNumber(token);
 
 1076     successful = decodeString(token);
 
 1080     currentValue().swapPayload(v);
 
 1081     currentValue().setOffsetStart(token.start_ - begin_);
 
 1082     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1086     currentValue().swapPayload(v);
 
 1087     currentValue().setOffsetStart(token.start_ - begin_);
 
 1088     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1092     currentValue().swapPayload(v);
 
 1093     currentValue().setOffsetStart(token.start_ - begin_);
 
 1094     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1097     Value v(std::numeric_limits<double>::quiet_NaN());
 
 1098     currentValue().swapPayload(v);
 
 1099     currentValue().setOffsetStart(token.start_ - begin_);
 
 1100     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1103     Value v(std::numeric_limits<double>::infinity());
 
 1104     currentValue().swapPayload(v);
 
 1105     currentValue().setOffsetStart(token.start_ - begin_);
 
 1106     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1109     Value v(-std::numeric_limits<double>::infinity());
 
 1110     currentValue().swapPayload(v);
 
 1111     currentValue().setOffsetStart(token.start_ - begin_);
 
 1112     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1114   case tokenArraySeparator:
 
 1115   case tokenObjectEnd:
 
 1117     if (features_.allowDroppedNullPlaceholders_) {
 
 1122       currentValue().swapPayload(v);
 
 1123       currentValue().setOffsetStart(current_ - begin_ - 1);
 
 1124       currentValue().setOffsetLimit(current_ - begin_);
 
 1128     currentValue().setOffsetStart(token.start_ - begin_);
 
 1129     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1130     return addError(
"Syntax error: value, object or array expected.", token);
 
 1133   if (collectComments_) {
 
 1134     lastValueEnd_ = current_;
 
 1135     lastValueHasAComment_ = 
false;
 
 1136     lastValue_ = ¤tValue();
 
 1142 void OurReader::skipCommentTokens(Token& token) {
 
 1143   if (features_.allowComments_) {
 
 1146     } 
while (token.type_ == tokenComment);
 
 1152 bool OurReader::readToken(Token& token) {
 
 1154   token.start_ = current_;
 
 1155   Char c = getNextChar();
 
 1159     token.type_ = tokenObjectBegin;
 
 1162     token.type_ = tokenObjectEnd;
 
 1165     token.type_ = tokenArrayBegin;
 
 1168     token.type_ = tokenArrayEnd;
 
 1171     token.type_ = tokenString;
 
 1175     if (features_.allowSingleQuotes_) {
 
 1176       token.type_ = tokenString;
 
 1177       ok = readStringSingleQuote();
 
 1181     token.type_ = tokenComment;
 
 1194     token.type_ = tokenNumber;
 
 1198     if (readNumber(
true)) {
 
 1199       token.type_ = tokenNumber;
 
 1201       token.type_ = tokenNegInf;
 
 1202       ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
 
 1206     if (readNumber(
true)) {
 
 1207       token.type_ = tokenNumber;
 
 1209       token.type_ = tokenPosInf;
 
 1210       ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
 
 1214     token.type_ = tokenTrue;
 
 1215     ok = match(
"rue", 3);
 
 1218     token.type_ = tokenFalse;
 
 1219     ok = match(
"alse", 4);
 
 1222     token.type_ = tokenNull;
 
 1223     ok = match(
"ull", 3);
 
 1226     if (features_.allowSpecialFloats_) {
 
 1227       token.type_ = tokenNaN;
 
 1228       ok = match(
"aN", 2);
 
 1234     if (features_.allowSpecialFloats_) {
 
 1235       token.type_ = tokenPosInf;
 
 1236       ok = match(
"nfinity", 7);
 
 1242     token.type_ = tokenArraySeparator;
 
 1245     token.type_ = tokenMemberSeparator;
 
 1248     token.type_ = tokenEndOfStream;
 
 1255     token.type_ = tokenError;
 
 1256   token.end_ = current_;
 
 1260 void OurReader::skipSpaces() {
 
 1261   while (current_ != end_) {
 
 1263     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
 
 1270 bool OurReader::match(
const Char* pattern, 
int patternLength) {
 
 1271   if (end_ - current_ < patternLength)
 
 1273   int index = patternLength;
 
 1275     if (current_[index] != pattern[index])
 
 1277   current_ += patternLength;
 
 1281 bool OurReader::readComment() {
 
 1282   const Location commentBegin = current_ - 1;
 
 1283   const Char c = getNextChar();
 
 1284   bool successful = 
false;
 
 1285   bool cStyleWithEmbeddedNewline = 
false;
 
 1287   const bool isCStyleComment = (c == 
'*');
 
 1288   const bool isCppStyleComment = (c == 
'/');
 
 1289   if (isCStyleComment) {
 
 1290     successful = readCStyleComment(&cStyleWithEmbeddedNewline);
 
 1291   } 
else if (isCppStyleComment) {
 
 1292     successful = readCppStyleComment();
 
 1298   if (collectComments_) {
 
 1301     if (!lastValueHasAComment_) {
 
 1302       if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
 
 1303         if (isCppStyleComment || !cStyleWithEmbeddedNewline) {
 
 1305           lastValueHasAComment_ = 
true;
 
 1310     addComment(commentBegin, current_, placement);
 
 1315 String OurReader::normalizeEOL(OurReader::Location begin,
 
 1316                                OurReader::Location end) {
 
 1318   normalized.reserve(
static_cast<size_t>(end - begin));
 
 1319   OurReader::Location current = begin;
 
 1320   while (current != end) {
 
 1321     char c = *current++;
 
 1323       if (current != end && *current == 
'\n')
 
 1335 void OurReader::addComment(Location begin, Location end,
 
 1337   assert(collectComments_);
 
 1338   const String& normalized = normalizeEOL(begin, end);
 
 1340     assert(lastValue_ != 
nullptr);
 
 1341     lastValue_->setComment(normalized, placement);
 
 1343     commentsBefore_ += normalized;
 
 1347 bool OurReader::readCStyleComment(
bool* containsNewLineResult) {
 
 1348   *containsNewLineResult = 
false;
 
 1350   while ((current_ + 1) < end_) {
 
 1351     Char c = getNextChar();
 
 1352     if (c == 
'*' && *current_ == 
'/') {
 
 1354     } 
else if (c == 
'\n') {
 
 1355       *containsNewLineResult = 
true;
 
 1359   return getNextChar() == 
'/';
 
 1362 bool OurReader::readCppStyleComment() {
 
 1363   while (current_ != end_) {
 
 1364     Char c = getNextChar();
 
 1369       if (current_ != end_ && *current_ == 
'\n')
 
 1378 bool OurReader::readNumber(
bool checkInf) {
 
 1379   Location p = current_;
 
 1380   if (checkInf && p != end_ && *p == 
'I') {
 
 1386   while (c >= 
'0' && c <= 
'9')
 
 1387     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1390     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1391     while (c >= 
'0' && c <= 
'9')
 
 1392       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1395   if (c == 
'e' || c == 
'E') {
 
 1396     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1397     if (c == 
'+' || c == 
'-')
 
 1398       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1399     while (c >= 
'0' && c <= 
'9')
 
 1400       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1404 bool OurReader::readString() {
 
 1406   while (current_ != end_) {
 
 1416 bool OurReader::readStringSingleQuote() {
 
 1418   while (current_ != end_) {
 
 1428 bool OurReader::readObject(Token& token) {
 
 1432   currentValue().swapPayload(init);
 
 1433   currentValue().setOffsetStart(token.start_ - begin_);
 
 1434   while (readToken(tokenName)) {
 
 1435     bool initialTokenOk = 
true;
 
 1436     while (tokenName.type_ == tokenComment && initialTokenOk)
 
 1437       initialTokenOk = readToken(tokenName);
 
 1438     if (!initialTokenOk)
 
 1440     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
 
 1443     if (tokenName.type_ == tokenString) {
 
 1444       if (!decodeString(tokenName, name))
 
 1445         return recoverFromError(tokenObjectEnd);
 
 1446     } 
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
 
 1448       if (!decodeNumber(tokenName, numberName))
 
 1449         return recoverFromError(tokenObjectEnd);
 
 1450       name = numberName.asString();
 
 1454     if (name.length() >= (1U << 30))
 
 1455       throwRuntimeError(
"keylength >= 2^30");
 
 1456     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
 
 1457       String msg = 
"Duplicate key: '" + name + 
"'";
 
 1458       return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
 
 1462     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
 
 1463       return addErrorAndRecover(
"Missing ':' after object member name", colon,
 
 1466     Value& value = currentValue()[name];
 
 1467     nodes_.push(&value);
 
 1468     bool ok = readValue();
 
 1471       return recoverFromError(tokenObjectEnd);
 
 1474     if (!readToken(comma) ||
 
 1475         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
 
 1476          comma.type_ != tokenComment)) {
 
 1477       return addErrorAndRecover(
"Missing ',' or '}' in object declaration",
 
 1478                                 comma, tokenObjectEnd);
 
 1480     bool finalizeTokenOk = 
true;
 
 1481     while (comma.type_ == tokenComment && finalizeTokenOk)
 
 1482       finalizeTokenOk = readToken(comma);
 
 1483     if (comma.type_ == tokenObjectEnd)
 
 1486   return addErrorAndRecover(
"Missing '}' or object member name", tokenName,
 
 1490 bool OurReader::readArray(Token& token) {
 
 1492   currentValue().swapPayload(init);
 
 1493   currentValue().setOffsetStart(token.start_ - begin_);
 
 1495   if (current_ != end_ && *current_ == 
']') 
 
 1498     readToken(endArray);
 
 1503     Value& value = currentValue()[index++];
 
 1504     nodes_.push(&value);
 
 1505     bool ok = readValue();
 
 1508       return recoverFromError(tokenArrayEnd);
 
 1512     ok = readToken(currentToken);
 
 1513     while (currentToken.type_ == tokenComment && ok) {
 
 1514       ok = readToken(currentToken);
 
 1516     bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
 
 1517                          currentToken.type_ != tokenArrayEnd);
 
 1518     if (!ok || badTokenType) {
 
 1519       return addErrorAndRecover(
"Missing ',' or ']' in array declaration",
 
 1520                                 currentToken, tokenArrayEnd);
 
 1522     if (currentToken.type_ == tokenArrayEnd)
 
 1528 bool OurReader::decodeNumber(Token& token) {
 
 1530   if (!decodeNumber(token, decoded))
 
 1532   currentValue().swapPayload(decoded);
 
 1533   currentValue().setOffsetStart(token.start_ - begin_);
 
 1534   currentValue().setOffsetLimit(token.end_ - begin_);
 
 1538 bool OurReader::decodeNumber(Token& token, Value& decoded) {
 
 1542   Location current = token.start_;
 
 1543   const bool isNegative = *current == 
'-';
 
 1552                 "Int must be smaller than UInt");
 
 1559                 "The absolute value of minLargestInt must be greater than or " 
 1560                 "equal to maxLargestInt");
 
 1562                 "The absolute value of minLargestInt must be only 1 magnitude " 
 1563                 "larger than maxLargest Int");
 
 1576   static constexpr 
Value::UInt negative_last_digit =
 
 1580       isNegative ? negative_threshold : positive_threshold;
 
 1582       isNegative ? negative_last_digit : positive_last_digit;
 
 1585   while (current < token.end_) {
 
 1586     Char c = *current++;
 
 1587     if (c < '0' || c > 
'9')
 
 1588       return decodeDouble(token, decoded);
 
 1591     if (value >= threshold) {
 
 1597       if (value > threshold || current != token.end_ ||
 
 1598           digit > max_last_digit) {
 
 1599         return decodeDouble(token, decoded);
 
 1602     value = value * 10 + digit;
 
 1618 bool OurReader::decodeDouble(Token& token) {
 
 1620   if (!decodeDouble(token, decoded))
 
 1622   currentValue().swapPayload(decoded);
 
 1623   currentValue().setOffsetStart(token.start_ - begin_);
 
 1624   currentValue().setOffsetLimit(token.end_ - begin_);
 
 1628 bool OurReader::decodeDouble(Token& token, Value& decoded) {
 
 1630   const String buffer(token.start_, token.end_);
 
 1632   if (!(is >> value)) {
 
 1634         "'" + 
String(token.start_, token.end_) + 
"' is not a number.", token);
 
 1640 bool OurReader::decodeString(Token& token) {
 
 1642   if (!decodeString(token, decoded_string))
 
 1644   Value decoded(decoded_string);
 
 1645   currentValue().swapPayload(decoded);
 
 1646   currentValue().setOffsetStart(token.start_ - begin_);
 
 1647   currentValue().setOffsetLimit(token.end_ - begin_);
 
 1651 bool OurReader::decodeString(Token& token, 
String& decoded) {
 
 1652   decoded.reserve(
static_cast<size_t>(token.end_ - token.start_ - 2));
 
 1653   Location current = token.start_ + 1; 
 
 1654   Location end = token.end_ - 1;       
 
 1655   while (current != end) {
 
 1656     Char c = *current++;
 
 1659     } 
else if (c == 
'\\') {
 
 1661         return addError(
"Empty escape sequence in string", token, current);
 
 1662       Char escape = *current++;
 
 1689         unsigned int unicode;
 
 1690         if (!decodeUnicodeCodePoint(token, current, end, unicode))
 
 1695         return addError(
"Bad escape sequence in string", token, current);
 
 1704 bool OurReader::decodeUnicodeCodePoint(Token& token, Location& current,
 
 1705                                        Location end, 
unsigned int& unicode) {
 
 1707   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
 
 1709   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
 
 1711     if (end - current < 6)
 
 1713           "additional six characters expected to parse unicode surrogate pair.",
 
 1715     if (*(current++) == 
'\\' && *(current++) == 
'u') {
 
 1716       unsigned int surrogatePair;
 
 1717       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
 
 1718         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
 
 1722       return addError(
"expecting another \\u token to begin the second half of " 
 1723                       "a unicode surrogate pair",
 
 1729 bool OurReader::decodeUnicodeEscapeSequence(Token& token, Location& current,
 
 1731                                             unsigned int& ret_unicode) {
 
 1732   if (end - current < 4)
 
 1734         "Bad unicode escape sequence in string: four digits expected.", token,
 
 1737   for (
int index = 0; index < 4; ++index) {
 
 1738     Char c = *current++;
 
 1740     if (c >= 
'0' && c <= 
'9')
 
 1742     else if (c >= 
'a' && c <= 
'f')
 
 1743       unicode += c - 
'a' + 10;
 
 1744     else if (c >= 
'A' && c <= 
'F')
 
 1745       unicode += c - 
'A' + 10;
 
 1748           "Bad unicode escape sequence in string: hexadecimal digit expected.",
 
 1751   ret_unicode = 
static_cast<unsigned int>(unicode);
 
 1755 bool OurReader::addError(
const String& message, Token& token, Location extra) {
 
 1757   info.token_ = token;
 
 1758   info.message_ = message;
 
 1759   info.extra_ = extra;
 
 1760   errors_.push_back(info);
 
 1764 bool OurReader::recoverFromError(TokenType skipUntilToken) {
 
 1765   size_t errorCount = errors_.size();
 
 1768     if (!readToken(skip))
 
 1769       errors_.resize(errorCount); 
 
 1770     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
 
 1773   errors_.resize(errorCount);
 
 1777 bool OurReader::addErrorAndRecover(
const String& message, Token& token,
 
 1778                                    TokenType skipUntilToken) {
 
 1779   addError(message, token);
 
 1780   return recoverFromError(skipUntilToken);
 
 1783 Value& OurReader::currentValue() { 
return *(nodes_.top()); }
 
 1785 OurReader::Char OurReader::getNextChar() {
 
 1786   if (current_ == end_)
 
 1791 void OurReader::getLocationLineAndColumn(Location location, 
int& line,
 
 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 String OurReader::getLocationLineAndColumn(Location location)
 const {
 
 1815   getLocationLineAndColumn(location, line, column);
 
 1816   char buffer[18 + 16 + 16 + 1];
 
 1817   jsoncpp_snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
 
 1821 String OurReader::getFormattedErrorMessages()
 const {
 
 1823   for (
const auto& error : errors_) {
 
 1825         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
 
 1826     formattedMessage += 
"  " + error.message_ + 
"\n";
 
 1829           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
 
 1831   return formattedMessage;
 
 1834 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
 const {
 
 1835   std::vector<OurReader::StructuredError> allErrors;
 
 1836   for (
const auto& error : errors_) {
 
 1837     OurReader::StructuredError structured;
 
 1838     structured.offset_start = error.token_.start_ - begin_;
 
 1839     structured.offset_limit = error.token_.end_ - begin_;
 
 1840     structured.message = error.message_;
 
 1841     allErrors.push_back(structured);
 
 1846 class OurCharReader : 
public CharReader {
 
 1847   bool const collectComments_;
 
 1851   OurCharReader(
bool collectComments, OurFeatures 
const& features)
 
 1852       : collectComments_(collectComments), reader_(features) {}
 
 1853   bool parse(
char const* beginDoc, 
char const* endDoc, Value* root,
 
 1855     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
 
 1857       *errs = reader_.getFormattedErrorMessages();
 
 1867   OurFeatures features = OurFeatures::all();
 
 1870   features.allowDroppedNullPlaceholders_ =
 
 1873   features.allowSingleQuotes_ = 
settings_[
"allowSingleQuotes"].
asBool();
 
 1877   features.stackLimit_ = 
static_cast<size_t>(
settings_[
"stackLimit"].
asUInt());
 
 1880   features.allowSpecialFloats_ = 
settings_[
"allowSpecialFloats"].
asBool();
 
 1881   return new OurCharReader(collectComments, features);
 
 1884   valid_keys->clear();
 
 1885   valid_keys->insert(
"collectComments");
 
 1886   valid_keys->insert(
"allowComments");
 
 1887   valid_keys->insert(
"strictRoot");
 
 1888   valid_keys->insert(
"allowDroppedNullPlaceholders");
 
 1889   valid_keys->insert(
"allowNumericKeys");
 
 1890   valid_keys->insert(
"allowSingleQuotes");
 
 1891   valid_keys->insert(
"stackLimit");
 
 1892   valid_keys->insert(
"failIfExtra");
 
 1893   valid_keys->insert(
"rejectDupKeys");
 
 1894   valid_keys->insert(
"allowSpecialFloats");
 
 1899     invalid = &my_invalid; 
 
 1901   std::set<String> valid_keys;
 
 1904   size_t n = keys.size();
 
 1905   for (
size_t i = 0; i < n; ++i) {
 
 1906     String const& key = keys[i];
 
 1907     if (valid_keys.find(key) == valid_keys.end()) {
 
 1919   (*settings)[
"allowComments"] = 
false;
 
 1920   (*settings)[
"strictRoot"] = 
true;
 
 1921   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
 
 1922   (*settings)[
"allowNumericKeys"] = 
false;
 
 1923   (*settings)[
"allowSingleQuotes"] = 
false;
 
 1924   (*settings)[
"stackLimit"] = 1000;
 
 1925   (*settings)[
"failIfExtra"] = 
true;
 
 1926   (*settings)[
"rejectDupKeys"] = 
true;
 
 1927   (*settings)[
"allowSpecialFloats"] = 
false;
 
 1933   (*settings)[
"collectComments"] = 
true;
 
 1934   (*settings)[
"allowComments"] = 
true;
 
 1935   (*settings)[
"strictRoot"] = 
false;
 
 1936   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
 
 1937   (*settings)[
"allowNumericKeys"] = 
false;
 
 1938   (*settings)[
"allowSingleQuotes"] = 
false;
 
 1939   (*settings)[
"stackLimit"] = 1000;
 
 1940   (*settings)[
"failIfExtra"] = 
false;
 
 1941   (*settings)[
"rejectDupKeys"] = 
false;
 
 1942   (*settings)[
"allowSpecialFloats"] = 
false;
 
 1952   ssin << sin.rdbuf();
 
 1954   char const* begin = doc.data();
 
 1955   char const* end = begin + doc.size();
 
 1958   return reader->parse(begin, end, root, errs);
 
 1966     throwRuntimeError(errs);