7 #if !defined(JSON_IS_AMALGAMATION) 
   12 #endif // if !defined(JSON_IS_AMALGAMATION) 
   23 #if __cplusplus >= 201103L 
   26 #define sscanf std::sscanf 
   32 #if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) 
   33 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 
   34 #endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 
   39 #pragma warning(disable : 4996) 
   44 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT) 
   45 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000 
   53 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) 
   79   for (; begin < end; ++begin)
 
   80     if (*begin == 
'\n' || *begin == 
'\r')
 
   89     : errors_(), document_(), commentsBefore_(), features_(Features::all()) {}
 
   91 Reader::Reader(
const Features& features)
 
   92     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
 
   93       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
 
   98                    bool collectComments) {
 
   99   document_.assign(document.begin(), document.end());
 
  100   const char* begin = document_.c_str();
 
  101   const char* end = begin + document_.length();
 
  102   return parse(begin, end, root, collectComments);
 
  114   std::getline(is, doc, (
char)EOF);
 
  115   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
 
  121                    bool collectComments) {
 
  123     collectComments = 
false;
 
  128   collectComments_ = collectComments;
 
  130   lastValueEnd_ = 
nullptr;
 
  131   lastValue_ = 
nullptr;
 
  132   commentsBefore_.clear();
 
  134   while (!nodes_.empty())
 
  138   bool successful = readValue();
 
  140   skipCommentTokens(token);
 
  141   if (collectComments_ && !commentsBefore_.empty())
 
  147       token.type_ = tokenError;
 
  148       token.start_ = beginDoc;
 
  151           "A valid JSON document must be either an array or an object value.",
 
  159 bool Reader::readValue() {
 
  168   skipCommentTokens(token);
 
  169   bool successful = 
true;
 
  171   if (collectComments_ && !commentsBefore_.empty()) {
 
  173     commentsBefore_.clear();
 
  176   switch (token.type_) {
 
  177   case tokenObjectBegin:
 
  178     successful = readObject(token);
 
  181   case tokenArrayBegin:
 
  182     successful = readArray(token);
 
  186     successful = decodeNumber(token);
 
  189     successful = decodeString(token);
 
  209   case tokenArraySeparator:
 
  225     return addError(
"Syntax error: value, object or array expected.", token);
 
  228   if (collectComments_) {
 
  229     lastValueEnd_ = current_;
 
  230     lastValue_ = ¤tValue();
 
  236 void Reader::skipCommentTokens(Token& token) {
 
  240     } 
while (token.type_ == tokenComment);
 
  246 bool Reader::readToken(Token& token) {
 
  248   token.start_ = current_;
 
  249   Char c = getNextChar();
 
  253     token.type_ = tokenObjectBegin;
 
  256     token.type_ = tokenObjectEnd;
 
  259     token.type_ = tokenArrayBegin;
 
  262     token.type_ = tokenArrayEnd;
 
  265     token.type_ = tokenString;
 
  269     token.type_ = tokenComment;
 
  283     token.type_ = tokenNumber;
 
  287     token.type_ = tokenTrue;
 
  288     ok = match(
"rue", 3);
 
  291     token.type_ = tokenFalse;
 
  292     ok = match(
"alse", 4);
 
  295     token.type_ = tokenNull;
 
  296     ok = match(
"ull", 3);
 
  299     token.type_ = tokenArraySeparator;
 
  302     token.type_ = tokenMemberSeparator;
 
  305     token.type_ = tokenEndOfStream;
 
  312     token.type_ = tokenError;
 
  313   token.end_ = current_;
 
  317 void Reader::skipSpaces() {
 
  318   while (current_ != end_) {
 
  320     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
 
  327 bool Reader::match(Location pattern, 
int patternLength) {
 
  328   if (end_ - current_ < patternLength)
 
  330   int index = patternLength;
 
  332     if (current_[index] != pattern[index])
 
  334   current_ += patternLength;
 
  338 bool Reader::readComment() {
 
  339   Location commentBegin = current_ - 1;
 
  340   Char c = getNextChar();
 
  341   bool successful = 
false;
 
  343     successful = readCStyleComment();
 
  345     successful = readCppStyleComment();
 
  349   if (collectComments_) {
 
  351     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
 
  352       if (c != 
'*' || !containsNewLine(commentBegin, current_))
 
  356     addComment(commentBegin, current_, placement);
 
  363   normalized.reserve(static_cast<size_t>(end - begin));
 
  365   while (current != end) {
 
  368       if (current != end && *current == 
'\n')
 
  380 void Reader::addComment(Location begin,
 
  383   assert(collectComments_);
 
  384   const String& normalized = normalizeEOL(begin, end);
 
  386     assert(lastValue_ != 
nullptr);
 
  387     lastValue_->
setComment(normalized, placement);
 
  389     commentsBefore_ += normalized;
 
  393 bool Reader::readCStyleComment() {
 
  394   while ((current_ + 1) < end_) {
 
  395     Char c = getNextChar();
 
  396     if (c == 
'*' && *current_ == 
'/')
 
  399   return getNextChar() == 
'/';
 
  402 bool Reader::readCppStyleComment() {
 
  403   while (current_ != end_) {
 
  404     Char c = getNextChar();
 
  409       if (current_ != end_ && *current_ == 
'\n')
 
  418 void Reader::readNumber() {
 
  419   const char* p = current_;
 
  422   while (c >= 
'0' && c <= 
'9')
 
  423     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  426     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  427     while (c >= 
'0' && c <= 
'9')
 
  428       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  431   if (c == 
'e' || c == 
'E') {
 
  432     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  433     if (c == 
'+' || c == 
'-')
 
  434       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  435     while (c >= 
'0' && c <= 
'9')
 
  436       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
  440 bool Reader::readString() {
 
  442   while (current_ != end_) {
 
  452 bool Reader::readObject(Token& token) {
 
  458   while (readToken(tokenName)) {
 
  459     bool initialTokenOk = 
true;
 
  460     while (tokenName.type_ == tokenComment && initialTokenOk)
 
  461       initialTokenOk = readToken(tokenName);
 
  464     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
 
  467     if (tokenName.type_ == tokenString) {
 
  468       if (!decodeString(tokenName, name))
 
  469         return recoverFromError(tokenObjectEnd);
 
  472       if (!decodeNumber(tokenName, numberName))
 
  473         return recoverFromError(tokenObjectEnd);
 
  474       name = 
String(numberName.asCString());
 
  480     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
 
  481       return addErrorAndRecover(
"Missing ':' after object member name", colon,
 
  484     Value& value = currentValue()[name];
 
  486     bool ok = readValue();
 
  489       return recoverFromError(tokenObjectEnd);
 
  492     if (!readToken(comma) ||
 
  493         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
 
  494          comma.type_ != tokenComment)) {
 
  495       return addErrorAndRecover(
"Missing ',' or '}' in object declaration",
 
  496                                 comma, tokenObjectEnd);
 
  498     bool finalizeTokenOk = 
true;
 
  499     while (comma.type_ == tokenComment && finalizeTokenOk)
 
  500       finalizeTokenOk = readToken(comma);
 
  501     if (comma.type_ == tokenObjectEnd)
 
  504   return addErrorAndRecover(
"Missing '}' or object member name", tokenName,
 
  508 bool Reader::readArray(Token& token) {
 
  513   if (current_ != end_ && *current_ == 
']') 
 
  521     Value& value = currentValue()[index++];
 
  523     bool ok = readValue();
 
  526       return recoverFromError(tokenArrayEnd);
 
  530     ok = readToken(currentToken);
 
  531     while (currentToken.type_ == tokenComment && ok) {
 
  532       ok = readToken(currentToken);
 
  534     bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
 
  535                          currentToken.type_ != tokenArrayEnd);
 
  536     if (!ok || badTokenType) {
 
  537       return addErrorAndRecover(
"Missing ',' or ']' in array declaration",
 
  538                                 currentToken, tokenArrayEnd);
 
  540     if (currentToken.type_ == tokenArrayEnd)
 
  546 bool Reader::decodeNumber(Token& token) {
 
  548   if (!decodeNumber(token, decoded))
 
  556 bool Reader::decodeNumber(Token& token, Value& decoded) {
 
  561   bool isNegative = *current == 
'-';
 
  571   while (current < token.end_) {
 
  573     if (c < '0' || c > 
'9')
 
  574       return decodeDouble(token, decoded);
 
  575     auto digit(static_cast<Value::UInt>(c - 
'0'));
 
  576     if (value >= threshold) {
 
  581       if (value > threshold || current != token.end_ ||
 
  582           digit > maxIntegerValue % 10) {
 
  583         return decodeDouble(token, decoded);
 
  586     value = value * 10 + digit;
 
  588   if (isNegative && value == maxIntegerValue)
 
  599 bool Reader::decodeDouble(Token& token) {
 
  601   if (!decodeDouble(token, decoded))
 
  609 bool Reader::decodeDouble(Token& token, Value& decoded) {
 
  611   String buffer(token.start_, token.end_);
 
  615         "'" + 
String(token.start_, token.end_) + 
"' is not a number.", token);
 
  620 bool Reader::decodeString(Token& token) {
 
  622   if (!decodeString(token, decoded_string))
 
  624   Value decoded(decoded_string);
 
  631 bool Reader::decodeString(Token& token, 
String& decoded) {
 
  632   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
 
  633   Location current = token.start_ + 1; 
 
  635   while (current != end) {
 
  639     else if (c == 
'\\') {
 
  641         return addError(
"Empty escape sequence in string", token, current);
 
  642       Char escape = *current++;
 
  669         unsigned int unicode;
 
  670         if (!decodeUnicodeCodePoint(token, current, end, unicode))
 
  675         return addError(
"Bad escape sequence in string", token, current);
 
  684 bool Reader::decodeUnicodeCodePoint(Token& token,
 
  687                                     unsigned int& unicode) {
 
  689   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
 
  691   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
 
  693     if (end - current < 6)
 
  695           "additional six characters expected to parse unicode surrogate pair.",
 
  697     if (*(current++) == 
'\\' && *(current++) == 
'u') {
 
  698       unsigned int surrogatePair;
 
  699       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
 
  700         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
 
  704       return addError(
"expecting another \\u token to begin the second half of " 
  705                       "a unicode surrogate pair",
 
  711 bool Reader::decodeUnicodeEscapeSequence(Token& token,
 
  714                                          unsigned int& ret_unicode) {
 
  715   if (end - current < 4)
 
  717         "Bad unicode escape sequence in string: four digits expected.", token,
 
  720   for (
int index = 0; index < 4; ++index) {
 
  723     if (c >= 
'0' && c <= 
'9')
 
  725     else if (c >= 
'a' && c <= 
'f')
 
  726       unicode += c - 
'a' + 10;
 
  727     else if (c >= 
'A' && c <= 
'F')
 
  728       unicode += c - 
'A' + 10;
 
  731           "Bad unicode escape sequence in string: hexadecimal digit expected.",
 
  734   ret_unicode = static_cast<unsigned int>(unicode);
 
  738 bool Reader::addError(
const String& message, Token& token, Location extra) {
 
  741   info.message_ = message;
 
  743   errors_.push_back(info);
 
  747 bool Reader::recoverFromError(TokenType skipUntilToken) {
 
  748   size_t const errorCount = errors_.size();
 
  751     if (!readToken(skip))
 
  752       errors_.resize(errorCount); 
 
  753     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
 
  756   errors_.resize(errorCount);
 
  760 bool Reader::addErrorAndRecover(
const String& message,
 
  762                                 TokenType skipUntilToken) {
 
  763   addError(message, token);
 
  764   return recoverFromError(skipUntilToken);
 
  767 Value& Reader::currentValue() { 
return *(nodes_.top()); }
 
  770   if (current_ == end_)
 
  775 void Reader::getLocationLineAndColumn(Location location,
 
  781   while (current < location && current != end_) {
 
  784       if (*current == 
'\n')
 
  786       lastLineStart = current;
 
  788     } 
else if (c == 
'\n') {
 
  789       lastLineStart = current;
 
  794   column = int(location - lastLineStart) + 1;
 
  798 String Reader::getLocationLineAndColumn(Location location)
 const {
 
  800   getLocationLineAndColumn(location, line, column);
 
  801   char buffer[18 + 16 + 16 + 1];
 
  802   jsoncpp_snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
 
  807 String Reader::getFormatedErrorMessages()
 const {
 
  813   for (
const auto& error : errors_) {
 
  815         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
 
  816     formattedMessage += 
"  " + error.message_ + 
"\n";
 
  819           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
 
  821   return formattedMessage;
 
  825   std::vector<Reader::StructuredError> allErrors;
 
  826   for (
const auto& error : errors_) {
 
  830     structured.
message = error.message_;
 
  831     allErrors.push_back(structured);
 
  837   ptrdiff_t 
const length = end_ - begin_;
 
  841   token.type_ = tokenError;
 
  846   info.message_ = message;
 
  847   info.extra_ = 
nullptr;
 
  848   errors_.push_back(info);
 
  854                        const Value& extra) {
 
  855   ptrdiff_t 
const length = end_ - begin_;
 
  860   token.type_ = tokenError;
 
  865   info.message_ = message;
 
  867   errors_.push_back(info);
 
  877   static OurFeatures all();
 
  880   bool allowDroppedNullPlaceholders_;
 
  881   bool allowNumericKeys_;
 
  882   bool allowSingleQuotes_;
 
  885   bool allowSpecialFloats_;
 
  889 OurFeatures OurFeatures::all() { 
return {}; }
 
  899   typedef const Char* Location;
 
  900   struct StructuredError {
 
  901     ptrdiff_t offset_start;
 
  902     ptrdiff_t offset_limit;
 
  906   OurReader(OurFeatures 
const& features);
 
  907   bool parse(
const char* beginDoc,
 
  910              bool collectComments = 
true);
 
  911   String getFormattedErrorMessages() 
const;
 
  912   std::vector<StructuredError> getStructuredErrors() 
const;
 
  913   bool pushError(
const Value& value, 
const String& message);
 
  914   bool pushError(
const Value& value, 
const String& message, 
const Value& extra);
 
  918   OurReader(OurReader 
const&);      
 
  919   void operator=(OurReader 
const&); 
 
  922     tokenEndOfStream = 0,
 
  936     tokenMemberSeparator,
 
  955   typedef std::deque<ErrorInfo> Errors;
 
  957   bool readToken(Token& token);
 
  959   bool match(Location pattern, 
int patternLength);
 
  961   bool readCStyleComment();
 
  962   bool readCppStyleComment();
 
  964   bool readStringSingleQuote();
 
  965   bool readNumber(
bool checkInf);
 
  967   bool readObject(Token& token);
 
  968   bool readArray(Token& token);
 
  969   bool decodeNumber(Token& token);
 
  970   bool decodeNumber(Token& token, Value& decoded);
 
  971   bool decodeString(Token& token);
 
  972   bool decodeString(Token& token, 
String& decoded);
 
  973   bool decodeDouble(Token& token);
 
  974   bool decodeDouble(Token& token, Value& decoded);
 
  975   bool decodeUnicodeCodePoint(Token& token,
 
  978                               unsigned int& unicode);
 
  979   bool decodeUnicodeEscapeSequence(Token& token,
 
  982                                    unsigned int& unicode);
 
  983   bool addError(
const String& message, Token& token, Location extra = 
nullptr);
 
  984   bool recoverFromError(TokenType skipUntilToken);
 
  985   bool addErrorAndRecover(
const String& message,
 
  987                           TokenType skipUntilToken);
 
  988   void skipUntilSpace();
 
  989   Value& currentValue();
 
  992   getLocationLineAndColumn(Location location, 
int& line, 
int& column) 
const;
 
  993   String getLocationLineAndColumn(Location location) 
const;
 
  995   void skipCommentTokens(Token& token);
 
  997   static String normalizeEOL(Location begin, Location end);
 
  998   static bool containsNewLine(Location begin, Location end);
 
 1000   typedef std::stack<Value*> Nodes;
 
 1007   Location lastValueEnd_;
 
 1011   OurFeatures 
const features_;
 
 1012   bool collectComments_;
 
 1017 bool OurReader::containsNewLine(OurReader::Location begin,
 
 1018                                 OurReader::Location end) {
 
 1019   for (; begin < end; ++begin)
 
 1020     if (*begin == 
'\n' || *begin == 
'\r')
 
 1025 OurReader::OurReader(OurFeatures 
const& features)
 
 1026     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
 
 1027       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
 
 1030 bool OurReader::parse(
const char* beginDoc,
 
 1033                       bool collectComments) {
 
 1034   if (!features_.allowComments_) {
 
 1035     collectComments = 
false;
 
 1040   collectComments_ = collectComments;
 
 1042   lastValueEnd_ = 
nullptr;
 
 1043   lastValue_ = 
nullptr;
 
 1044   commentsBefore_.clear();
 
 1046   while (!nodes_.empty())
 
 1050   bool successful = readValue();
 
 1053   skipCommentTokens(token);
 
 1054   if (features_.failIfExtra_) {
 
 1055     if ((features_.strictRoot_ || token.type_ != tokenError) &&
 
 1056         token.type_ != tokenEndOfStream) {
 
 1057       addError(
"Extra non-whitespace after JSON value.", token);
 
 1061   if (collectComments_ && !commentsBefore_.empty())
 
 1063   if (features_.strictRoot_) {
 
 1064     if (!root.isArray() && !root.isObject()) {
 
 1067       token.type_ = tokenError;
 
 1068       token.start_ = beginDoc;
 
 1069       token.end_ = endDoc;
 
 1071           "A valid JSON document must be either an array or an object value.",
 
 1079 bool OurReader::readValue() {
 
 1081   if (nodes_.size() > features_.stackLimit_)
 
 1084   skipCommentTokens(token);
 
 1085   bool successful = 
true;
 
 1087   if (collectComments_ && !commentsBefore_.empty()) {
 
 1089     commentsBefore_.clear();
 
 1092   switch (token.type_) {
 
 1093   case tokenObjectBegin:
 
 1094     successful = readObject(token);
 
 1095     currentValue().setOffsetLimit(current_ - begin_);
 
 1097   case tokenArrayBegin:
 
 1098     successful = readArray(token);
 
 1099     currentValue().setOffsetLimit(current_ - begin_);
 
 1102     successful = decodeNumber(token);
 
 1105     successful = decodeString(token);
 
 1109     currentValue().swapPayload(v);
 
 1110     currentValue().setOffsetStart(token.start_ - begin_);
 
 1111     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1115     currentValue().swapPayload(v);
 
 1116     currentValue().setOffsetStart(token.start_ - begin_);
 
 1117     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1121     currentValue().swapPayload(v);
 
 1122     currentValue().setOffsetStart(token.start_ - begin_);
 
 1123     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1126     Value v(std::numeric_limits<double>::quiet_NaN());
 
 1127     currentValue().swapPayload(v);
 
 1128     currentValue().setOffsetStart(token.start_ - begin_);
 
 1129     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1132     Value v(std::numeric_limits<double>::infinity());
 
 1133     currentValue().swapPayload(v);
 
 1134     currentValue().setOffsetStart(token.start_ - begin_);
 
 1135     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1138     Value v(-std::numeric_limits<double>::infinity());
 
 1139     currentValue().swapPayload(v);
 
 1140     currentValue().setOffsetStart(token.start_ - begin_);
 
 1141     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1143   case tokenArraySeparator:
 
 1144   case tokenObjectEnd:
 
 1146     if (features_.allowDroppedNullPlaceholders_) {
 
 1151       currentValue().swapPayload(v);
 
 1152       currentValue().setOffsetStart(current_ - begin_ - 1);
 
 1153       currentValue().setOffsetLimit(current_ - begin_);
 
 1157     currentValue().setOffsetStart(token.start_ - begin_);
 
 1158     currentValue().setOffsetLimit(token.end_ - begin_);
 
 1159     return addError(
"Syntax error: value, object or array expected.", token);
 
 1162   if (collectComments_) {
 
 1163     lastValueEnd_ = current_;
 
 1164     lastValue_ = ¤tValue();
 
 1170 void OurReader::skipCommentTokens(Token& token) {
 
 1171   if (features_.allowComments_) {
 
 1174     } 
while (token.type_ == tokenComment);
 
 1180 bool OurReader::readToken(Token& token) {
 
 1182   token.start_ = current_;
 
 1183   Char c = getNextChar();
 
 1187     token.type_ = tokenObjectBegin;
 
 1190     token.type_ = tokenObjectEnd;
 
 1193     token.type_ = tokenArrayBegin;
 
 1196     token.type_ = tokenArrayEnd;
 
 1199     token.type_ = tokenString;
 
 1203     if (features_.allowSingleQuotes_) {
 
 1204       token.type_ = tokenString;
 
 1205       ok = readStringSingleQuote();
 
 1209     token.type_ = tokenComment;
 
 1222     token.type_ = tokenNumber;
 
 1226     if (readNumber(
true)) {
 
 1227       token.type_ = tokenNumber;
 
 1229       token.type_ = tokenNegInf;
 
 1230       ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
 
 1234     token.type_ = tokenTrue;
 
 1235     ok = match(
"rue", 3);
 
 1238     token.type_ = tokenFalse;
 
 1239     ok = match(
"alse", 4);
 
 1242     token.type_ = tokenNull;
 
 1243     ok = match(
"ull", 3);
 
 1246     if (features_.allowSpecialFloats_) {
 
 1247       token.type_ = tokenNaN;
 
 1248       ok = match(
"aN", 2);
 
 1254     if (features_.allowSpecialFloats_) {
 
 1255       token.type_ = tokenPosInf;
 
 1256       ok = match(
"nfinity", 7);
 
 1262     token.type_ = tokenArraySeparator;
 
 1265     token.type_ = tokenMemberSeparator;
 
 1268     token.type_ = tokenEndOfStream;
 
 1275     token.type_ = tokenError;
 
 1276   token.end_ = current_;
 
 1280 void OurReader::skipSpaces() {
 
 1281   while (current_ != end_) {
 
 1283     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
 
 1290 bool OurReader::match(Location pattern, 
int patternLength) {
 
 1291   if (end_ - current_ < patternLength)
 
 1293   int index = patternLength;
 
 1295     if (current_[index] != pattern[index])
 
 1297   current_ += patternLength;
 
 1301 bool OurReader::readComment() {
 
 1302   Location commentBegin = current_ - 1;
 
 1303   Char c = getNextChar();
 
 1304   bool successful = 
false;
 
 1306     successful = readCStyleComment();
 
 1308     successful = readCppStyleComment();
 
 1312   if (collectComments_) {
 
 1314     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
 
 1315       if (c != 
'*' || !containsNewLine(commentBegin, current_))
 
 1319     addComment(commentBegin, current_, placement);
 
 1324 String OurReader::normalizeEOL(OurReader::Location begin,
 
 1325                                OurReader::Location end) {
 
 1327   normalized.reserve(static_cast<size_t>(end - begin));
 
 1328   OurReader::Location current = begin;
 
 1329   while (current != end) {
 
 1330     char c = *current++;
 
 1332       if (current != end && *current == 
'\n')
 
 1344 void OurReader::addComment(Location begin,
 
 1347   assert(collectComments_);
 
 1348   const String& normalized = normalizeEOL(begin, end);
 
 1350     assert(lastValue_ != 
nullptr);
 
 1351     lastValue_->setComment(normalized, placement);
 
 1353     commentsBefore_ += normalized;
 
 1357 bool OurReader::readCStyleComment() {
 
 1358   while ((current_ + 1) < end_) {
 
 1359     Char c = getNextChar();
 
 1360     if (c == 
'*' && *current_ == 
'/')
 
 1363   return getNextChar() == 
'/';
 
 1366 bool OurReader::readCppStyleComment() {
 
 1367   while (current_ != end_) {
 
 1368     Char c = getNextChar();
 
 1373       if (current_ != end_ && *current_ == 
'\n')
 
 1382 bool OurReader::readNumber(
bool checkInf) {
 
 1383   const char* p = current_;
 
 1384   if (checkInf && p != end_ && *p == 
'I') {
 
 1390   while (c >= 
'0' && c <= 
'9')
 
 1391     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1394     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1395     while (c >= 
'0' && c <= 
'9')
 
 1396       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1399   if (c == 
'e' || c == 
'E') {
 
 1400     c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1401     if (c == 
'+' || c == 
'-')
 
 1402       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1403     while (c >= 
'0' && c <= 
'9')
 
 1404       c = (current_ = p) < end_ ? *p++ : 
'\0';
 
 1408 bool OurReader::readString() {
 
 1410   while (current_ != end_) {
 
 1420 bool OurReader::readStringSingleQuote() {
 
 1422   while (current_ != end_) {
 
 1432 bool OurReader::readObject(Token& token) {
 
 1436   currentValue().swapPayload(init);
 
 1437   currentValue().setOffsetStart(token.start_ - begin_);
 
 1438   while (readToken(tokenName)) {
 
 1439     bool initialTokenOk = 
true;
 
 1440     while (tokenName.type_ == tokenComment && initialTokenOk)
 
 1441       initialTokenOk = readToken(tokenName);
 
 1442     if (!initialTokenOk)
 
 1444     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
 
 1447     if (tokenName.type_ == tokenString) {
 
 1448       if (!decodeString(tokenName, name))
 
 1449         return recoverFromError(tokenObjectEnd);
 
 1450     } 
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
 
 1452       if (!decodeNumber(tokenName, numberName))
 
 1453         return recoverFromError(tokenObjectEnd);
 
 1454       name = numberName.asString();
 
 1458     if (name.length() >= (1U << 30))
 
 1460     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
 
 1461       String msg = 
"Duplicate key: '" + name + 
"'";
 
 1462       return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
 
 1466     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
 
 1467       return addErrorAndRecover(
"Missing ':' after object member name", colon,
 
 1470     Value& value = currentValue()[name];
 
 1471     nodes_.push(&value);
 
 1472     bool ok = readValue();
 
 1475       return recoverFromError(tokenObjectEnd);
 
 1478     if (!readToken(comma) ||
 
 1479         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
 
 1480          comma.type_ != tokenComment)) {
 
 1481       return addErrorAndRecover(
"Missing ',' or '}' in object declaration",
 
 1482                                 comma, tokenObjectEnd);
 
 1484     bool finalizeTokenOk = 
true;
 
 1485     while (comma.type_ == tokenComment && finalizeTokenOk)
 
 1486       finalizeTokenOk = readToken(comma);
 
 1487     if (comma.type_ == tokenObjectEnd)
 
 1490   return addErrorAndRecover(
"Missing '}' or object member name", tokenName,
 
 1494 bool OurReader::readArray(Token& token) {
 
 1496   currentValue().swapPayload(init);
 
 1497   currentValue().setOffsetStart(token.start_ - begin_);
 
 1499   if (current_ != end_ && *current_ == 
']') 
 
 1502     readToken(endArray);
 
 1507     Value& value = currentValue()[index++];
 
 1508     nodes_.push(&value);
 
 1509     bool ok = readValue();
 
 1512       return recoverFromError(tokenArrayEnd);
 
 1516     ok = readToken(currentToken);
 
 1517     while (currentToken.type_ == tokenComment && ok) {
 
 1518       ok = readToken(currentToken);
 
 1520     bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
 
 1521                          currentToken.type_ != tokenArrayEnd);
 
 1522     if (!ok || badTokenType) {
 
 1523       return addErrorAndRecover(
"Missing ',' or ']' in array declaration",
 
 1524                                 currentToken, tokenArrayEnd);
 
 1526     if (currentToken.type_ == tokenArrayEnd)
 
 1532 bool OurReader::decodeNumber(Token& token) {
 
 1534   if (!decodeNumber(token, decoded))
 
 1536   currentValue().swapPayload(decoded);
 
 1537   currentValue().setOffsetStart(token.start_ - begin_);
 
 1538   currentValue().setOffsetLimit(token.end_ - begin_);
 
 1542 bool OurReader::decodeNumber(Token& token, Value& decoded) {
 
 1546   Location current = token.start_;
 
 1547   bool isNegative = *current == 
'-';
 
 1554   static const auto negative_threshold =
 
 1556   static const auto negative_last_digit =
 
 1559   const auto threshold = isNegative ? negative_threshold : positive_threshold;
 
 1560   const auto last_digit =
 
 1561       isNegative ? negative_last_digit : positive_last_digit;
 
 1564   while (current < token.end_) {
 
 1565     Char c = *current++;
 
 1566     if (c < '0' || c > 
'9')
 
 1567       return decodeDouble(token, decoded);
 
 1569     const auto digit(static_cast<Value::UInt>(c - 
'0'));
 
 1570     if (value >= threshold) {
 
 1576       if (value > threshold || current != token.end_ || digit > last_digit) {
 
 1577         return decodeDouble(token, decoded);
 
 1580     value = value * 10 + digit;
 
 1593 bool OurReader::decodeDouble(Token& token) {
 
 1595   if (!decodeDouble(token, decoded))
 
 1597   currentValue().swapPayload(decoded);
 
 1598   currentValue().setOffsetStart(token.start_ - begin_);
 
 1599   currentValue().setOffsetLimit(token.end_ - begin_);
 
 1603 bool OurReader::decodeDouble(Token& token, Value& decoded) {
 
 1605   const int bufferSize = 32;
 
 1607   ptrdiff_t 
const length = token.end_ - token.start_;
 
 1611     return addError(
"Unable to parse token length", token);
 
 1613   auto const ulength = static_cast<size_t>(length);
 
 1620   char format[] = 
"%lf";
 
 1622   if (length <= bufferSize) {
 
 1623     Char buffer[bufferSize + 1];
 
 1624     memcpy(buffer, token.start_, ulength);
 
 1627     count = sscanf(buffer, format, &value);
 
 1629     String buffer(token.start_, token.end_);
 
 1630     count = sscanf(buffer.c_str(), format, &value);
 
 1635         "'" + 
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,
 
 1707                                        unsigned int& unicode) {
 
 1709   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
 
 1711   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
 
 1713     if (end - current < 6)
 
 1715           "additional six characters expected to parse unicode surrogate pair.",
 
 1717     if (*(current++) == 
'\\' && *(current++) == 
'u') {
 
 1718       unsigned int surrogatePair;
 
 1719       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
 
 1720         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
 
 1724       return addError(
"expecting another \\u token to begin the second half of " 
 1725                       "a unicode surrogate pair",
 
 1731 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
 
 1734                                             unsigned int& ret_unicode) {
 
 1735   if (end - current < 4)
 
 1737         "Bad unicode escape sequence in string: four digits expected.", token,
 
 1740   for (
int index = 0; index < 4; ++index) {
 
 1741     Char c = *current++;
 
 1743     if (c >= 
'0' && c <= 
'9')
 
 1745     else if (c >= 
'a' && c <= 
'f')
 
 1746       unicode += c - 
'a' + 10;
 
 1747     else if (c >= 
'A' && c <= 
'F')
 
 1748       unicode += c - 
'A' + 10;
 
 1751           "Bad unicode escape sequence in string: hexadecimal digit expected.",
 
 1754   ret_unicode = static_cast<unsigned int>(unicode);
 
 1758 bool OurReader::addError(
const String& message, Token& token, Location extra) {
 
 1760   info.token_ = token;
 
 1761   info.message_ = message;
 
 1762   info.extra_ = extra;
 
 1763   errors_.push_back(info);
 
 1767 bool OurReader::recoverFromError(TokenType skipUntilToken) {
 
 1768   size_t errorCount = errors_.size();
 
 1771     if (!readToken(skip))
 
 1772       errors_.resize(errorCount); 
 
 1773     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
 
 1776   errors_.resize(errorCount);
 
 1780 bool OurReader::addErrorAndRecover(
const String& message,
 
 1782                                    TokenType skipUntilToken) {
 
 1783   addError(message, token);
 
 1784   return recoverFromError(skipUntilToken);
 
 1787 Value& OurReader::currentValue() { 
return *(nodes_.top()); }
 
 1789 OurReader::Char OurReader::getNextChar() {
 
 1790   if (current_ == end_)
 
 1795 void OurReader::getLocationLineAndColumn(Location location,
 
 1797                                          int& column)
 const {
 
 1798   Location current = begin_;
 
 1799   Location lastLineStart = current;
 
 1801   while (current < location && current != end_) {
 
 1802     Char c = *current++;
 
 1804       if (*current == 
'\n')
 
 1806       lastLineStart = current;
 
 1808     } 
else if (c == 
'\n') {
 
 1809       lastLineStart = current;
 
 1814   column = int(location - lastLineStart) + 1;
 
 1818 String OurReader::getLocationLineAndColumn(Location location)
 const {
 
 1820   getLocationLineAndColumn(location, line, column);
 
 1821   char buffer[18 + 16 + 16 + 1];
 
 1822   jsoncpp_snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
 
 1826 String OurReader::getFormattedErrorMessages()
 const {
 
 1828   for (
const auto& error : errors_) {
 
 1830         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
 
 1831     formattedMessage += 
"  " + error.message_ + 
"\n";
 
 1834           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
 
 1836   return formattedMessage;
 
 1839 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
 const {
 
 1840   std::vector<OurReader::StructuredError> allErrors;
 
 1841   for (
const auto& error : errors_) {
 
 1842     OurReader::StructuredError structured;
 
 1843     structured.offset_start = error.token_.start_ - begin_;
 
 1844     structured.offset_limit = error.token_.end_ - begin_;
 
 1845     structured.message = error.message_;
 
 1846     allErrors.push_back(structured);
 
 1851 bool OurReader::pushError(
const Value& value, 
const String& message) {
 
 1852   ptrdiff_t length = end_ - begin_;
 
 1853   if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
 
 1856   token.type_ = tokenError;
 
 1857   token.start_ = begin_ + value.getOffsetStart();
 
 1858   token.end_ = begin_ + value.getOffsetLimit();
 
 1860   info.token_ = token;
 
 1861   info.message_ = message;
 
 1862   info.extra_ = 
nullptr;
 
 1863   errors_.push_back(info);
 
 1867 bool OurReader::pushError(
const Value& value,
 
 1869                           const Value& extra) {
 
 1870   ptrdiff_t length = end_ - begin_;
 
 1871   if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
 
 1872       extra.getOffsetLimit() > length)
 
 1875   token.type_ = tokenError;
 
 1876   token.start_ = begin_ + value.getOffsetStart();
 
 1877   token.end_ = begin_ + value.getOffsetLimit();
 
 1879   info.token_ = token;
 
 1880   info.message_ = message;
 
 1881   info.extra_ = begin_ + extra.getOffsetStart();
 
 1882   errors_.push_back(info);
 
 1886 bool OurReader::good()
 const { 
return errors_.empty(); }
 
 1888 class OurCharReader : 
public CharReader {
 
 1889   bool const collectComments_;
 
 1893   OurCharReader(
bool collectComments, OurFeatures 
const& features)
 
 1894       : collectComments_(collectComments), reader_(features) {}
 
 1895   bool parse(
char const* beginDoc,
 
 1899     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
 
 1901       *errs = reader_.getFormattedErrorMessages();
 
 1911   OurFeatures features = OurFeatures::all();
 
 1914   features.allowDroppedNullPlaceholders_ =
 
 1917   features.allowSingleQuotes_ = 
settings_[
"allowSingleQuotes"].
asBool();
 
 1921   features.stackLimit_ = static_cast<size_t>(
settings_[
"stackLimit"].asUInt());
 
 1924   features.allowSpecialFloats_ = 
settings_[
"allowSpecialFloats"].
asBool();
 
 1925   return new OurCharReader(collectComments, features);
 
 1928   valid_keys->clear();
 
 1929   valid_keys->insert(
"collectComments");
 
 1930   valid_keys->insert(
"allowComments");
 
 1931   valid_keys->insert(
"strictRoot");
 
 1932   valid_keys->insert(
"allowDroppedNullPlaceholders");
 
 1933   valid_keys->insert(
"allowNumericKeys");
 
 1934   valid_keys->insert(
"allowSingleQuotes");
 
 1935   valid_keys->insert(
"stackLimit");
 
 1936   valid_keys->insert(
"failIfExtra");
 
 1937   valid_keys->insert(
"rejectDupKeys");
 
 1938   valid_keys->insert(
"allowSpecialFloats");
 
 1943     invalid = &my_invalid; 
 
 1945   std::set<String> valid_keys;
 
 1948   size_t n = keys.size();
 
 1949   for (
size_t i = 0; i < n; ++i) {
 
 1950     String const& key = keys[i];
 
 1951     if (valid_keys.find(key) == valid_keys.end()) {
 
 1963   (*settings)[
"allowComments"] = 
false;
 
 1964   (*settings)[
"strictRoot"] = 
true;
 
 1965   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
 
 1966   (*settings)[
"allowNumericKeys"] = 
false;
 
 1967   (*settings)[
"allowSingleQuotes"] = 
false;
 
 1968   (*settings)[
"stackLimit"] = 1000;
 
 1969   (*settings)[
"failIfExtra"] = 
true;
 
 1970   (*settings)[
"rejectDupKeys"] = 
true;
 
 1971   (*settings)[
"allowSpecialFloats"] = 
false;
 
 1977   (*settings)[
"collectComments"] = 
true;
 
 1978   (*settings)[
"allowComments"] = 
true;
 
 1979   (*settings)[
"strictRoot"] = 
false;
 
 1980   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
 
 1981   (*settings)[
"allowNumericKeys"] = 
false;
 
 1982   (*settings)[
"allowSingleQuotes"] = 
false;
 
 1983   (*settings)[
"stackLimit"] = 1000;
 
 1984   (*settings)[
"failIfExtra"] = 
false;
 
 1985   (*settings)[
"rejectDupKeys"] = 
false;
 
 1986   (*settings)[
"allowSpecialFloats"] = 
false;
 
 1998   ssin << sin.rdbuf();
 
 2000   char const* begin = doc.data();
 
 2001   char const* end = begin + doc.size();
 
 2004   return reader->parse(begin, end, root, errs);