7 #if !defined(JSON_IS_AMALGAMATION)    12 #endif // if !defined(JSON_IS_AMALGAMATION)    24 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above     25 #define snprintf sprintf_s    26 #elif _MSC_VER >= 1900 // VC++ 14.0 and above    27 #define snprintf std::snprintf    29 #define snprintf _snprintf    31 #elif defined(__ANDROID__) || defined(__QNXNTO__)    32 #define snprintf snprintf    33 #elif __cplusplus >= 201103L    34 #if !defined(__MINGW32__) && !defined(__CYGWIN__)    35 #define snprintf std::snprintf    39 #if defined(__QNXNTO__)    40 #define sscanf std::sscanf    43 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0    45 #pragma warning(disable : 4996)    49 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)    50 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000    57 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)    67     : allowComments_(true), strictRoot_(false),
    68       allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
    85   for (; begin < end; ++begin)
    86     if (*begin == 
'\n' || *begin == 
'\r')
    95     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
    96       lastValue_(), commentsBefore_(), features_(
Features::
all()),
   100     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
   101       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
   106   JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
   107   std::swap(documentCopy, document_);
   108   const char* begin = document_.c_str();
   109   const char* end = begin + document_.length();
   110   return parse(begin, end, root, collectComments);
   122   std::getline(sin, doc, (
char)EOF);
   123   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
   129                    bool collectComments) {
   131     collectComments = 
false;
   136   collectComments_ = collectComments;
   140   commentsBefore_.clear();
   142   while (!nodes_.empty())
   146   bool successful = readValue();
   148   skipCommentTokens(token);
   149   if (collectComments_ && !commentsBefore_.empty())
   155       token.type_ = tokenError;
   156       token.start_ = beginDoc;
   159           "A valid JSON document must be either an array or an object value.",
   167 bool Reader::readValue() {
   171   if (nodes_.size() > 
stackLimit_g) throwRuntimeError(
"Exceeded stackLimit in readValue().");
   174   skipCommentTokens(token);
   175   bool successful = 
true;
   177   if (collectComments_ && !commentsBefore_.empty()) {
   179     commentsBefore_.clear();
   182   switch (token.type_) {
   183   case tokenObjectBegin:
   184     successful = readObject(token);
   187   case tokenArrayBegin:
   188     successful = readArray(token);
   192     successful = decodeNumber(token);
   195     successful = decodeString(token);
   221   case tokenArraySeparator:
   237     return addError(
"Syntax error: value, object or array expected.", token);
   240   if (collectComments_) {
   241     lastValueEnd_ = current_;
   242     lastValue_ = ¤tValue();
   248 void Reader::skipCommentTokens(Token& token) {
   252     } 
while (token.type_ == tokenComment);
   258 bool Reader::readToken(Token& token) {
   260   token.start_ = current_;
   261   Char c = getNextChar();
   265     token.type_ = tokenObjectBegin;
   268     token.type_ = tokenObjectEnd;
   271     token.type_ = tokenArrayBegin;
   274     token.type_ = tokenArrayEnd;
   277     token.type_ = tokenString;
   281     token.type_ = tokenComment;
   295     token.type_ = tokenNumber;
   299     token.type_ = tokenTrue;
   300     ok = match(
"rue", 3);
   303     token.type_ = tokenFalse;
   304     ok = match(
"alse", 4);
   307     token.type_ = tokenNull;
   308     ok = match(
"ull", 3);
   311     token.type_ = tokenArraySeparator;
   314     token.type_ = tokenMemberSeparator;
   317     token.type_ = tokenEndOfStream;
   324     token.type_ = tokenError;
   325   token.end_ = current_;
   329 void Reader::skipSpaces() {
   330   while (current_ != end_) {
   332     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
   339 bool Reader::match(
Location pattern, 
int patternLength) {
   340   if (end_ - current_ < patternLength)
   342   int index = patternLength;
   344     if (current_[index] != pattern[index])
   346   current_ += patternLength;
   350 bool Reader::readComment() {
   351   Location commentBegin = current_ - 1;
   352   Char c = getNextChar();
   353   bool successful = 
false;
   355     successful = readCStyleComment();
   357     successful = readCppStyleComment();
   361   if (collectComments_) {
   368     addComment(commentBegin, current_, placement);
   375   normalized.reserve(static_cast<size_t>(end - begin));
   377   while (current != end) {
   380       if (current != end && *current == 
'\n')
   394   assert(collectComments_);
   397     assert(lastValue_ != 0);
   398     lastValue_->
setComment(normalized, placement);
   400     commentsBefore_ += normalized;
   404 bool Reader::readCStyleComment() {
   405   while ((current_ + 1) < end_) {
   406     Char c = getNextChar();
   407     if (c == 
'*' && *current_ == 
'/')
   410   return getNextChar() == 
'/';
   413 bool Reader::readCppStyleComment() {
   414   while (current_ != end_) {
   415     Char c = getNextChar();
   420       if (current_ != end_ && *current_ == 
'\n')
   429 void Reader::readNumber() {
   430   const char *p = current_;
   433   while (c >= 
'0' && c <= 
'9')
   434     c = (current_ = p) < end_ ? *p++ : 
'\0';
   437     c = (current_ = p) < end_ ? *p++ : 
'\0';
   438     while (c >= 
'0' && c <= 
'9')
   439       c = (current_ = p) < end_ ? *p++ : 
'\0';
   442   if (c == 
'e' || c == 
'E') {
   443     c = (current_ = p) < end_ ? *p++ : 
'\0';
   444     if (c == 
'+' || c == 
'-')
   445       c = (current_ = p) < end_ ? *p++ : 
'\0';
   446     while (c >= 
'0' && c <= 
'9')
   447       c = (current_ = p) < end_ ? *p++ : 
'\0';
   451 bool Reader::readString() {
   453   while (current_ != end_) {
   463 bool Reader::readObject(Token& tokenStart) {
   469   while (readToken(tokenName)) {
   470     bool initialTokenOk = 
true;
   471     while (tokenName.type_ == tokenComment && initialTokenOk)
   472       initialTokenOk = readToken(tokenName);
   475     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
   478     if (tokenName.type_ == tokenString) {
   479       if (!decodeString(tokenName, name))
   480         return recoverFromError(tokenObjectEnd);
   483       if (!decodeNumber(tokenName, numberName))
   484         return recoverFromError(tokenObjectEnd);
   491     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
   492       return addErrorAndRecover(
   493           "Missing ':' after object member name", colon, tokenObjectEnd);
   495     Value& value = currentValue()[name];
   497     bool ok = readValue();
   500       return recoverFromError(tokenObjectEnd);
   503     if (!readToken(comma) ||
   504         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
   505          comma.type_ != tokenComment)) {
   506       return addErrorAndRecover(
   507           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
   509     bool finalizeTokenOk = 
true;
   510     while (comma.type_ == tokenComment && finalizeTokenOk)
   511       finalizeTokenOk = readToken(comma);
   512     if (comma.type_ == tokenObjectEnd)
   515   return addErrorAndRecover(
   516       "Missing '}' or object member name", tokenName, tokenObjectEnd);
   519 bool Reader::readArray(Token& tokenStart) {
   524   if (current_ != end_ && *current_ == 
']') 
   532     Value& value = currentValue()[index++];
   534     bool ok = readValue();
   537       return recoverFromError(tokenArrayEnd);
   541     ok = readToken(token);
   542     while (token.type_ == tokenComment && ok) {
   543       ok = readToken(token);
   546         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
   547     if (!ok || badTokenType) {
   548       return addErrorAndRecover(
   549           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
   551     if (token.type_ == tokenArrayEnd)
   557 bool Reader::decodeNumber(Token& token) {
   559   if (!decodeNumber(token, decoded))
   567 bool Reader::decodeNumber(Token& token, 
Value& decoded) {
   572   bool isNegative = *current == 
'-';
   581   while (current < token.end_) {
   583     if (c < '0' || c > 
'9')
   584       return decodeDouble(token, decoded);
   585     Value::UInt digit(static_cast<Value::UInt>(c - 
'0'));
   586     if (value >= threshold) {
   591       if (value > threshold || current != token.end_ ||
   592           digit > maxIntegerValue % 10) {
   593         return decodeDouble(token, decoded);
   596     value = value * 10 + digit;
   598   if (isNegative && value == maxIntegerValue)
   609 bool Reader::decodeDouble(Token& token) {
   611   if (!decodeDouble(token, decoded))
   619 bool Reader::decodeDouble(Token& token, 
Value& decoded) {
   625                         "' is not a number.",
   631 bool Reader::decodeString(Token& token) {
   633   if (!decodeString(token, decoded_string))
   635   Value decoded(decoded_string);
   642 bool Reader::decodeString(Token& token, 
JSONCPP_STRING& decoded) {
   643   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
   644   Location current = token.start_ + 1; 
   646   while (current != end) {
   650     else if (c == 
'\\') {
   652         return addError(
"Empty escape sequence in string", token, current);
   653       Char escape = *current++;
   680         unsigned int unicode;
   681         if (!decodeUnicodeCodePoint(token, current, end, unicode))
   686         return addError(
"Bad escape sequence in string", token, current);
   695 bool Reader::decodeUnicodeCodePoint(Token& token,
   698                                     unsigned int& unicode) {
   700   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
   702   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
   704     if (end - current < 6)
   706           "additional six characters expected to parse unicode surrogate pair.",
   709     unsigned int surrogatePair;
   710     if (*(current++) == 
'\\' && *(current++) == 
'u') {
   711       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
   712         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
   716       return addError(
"expecting another \\u token to begin the second half of "   717                       "a unicode surrogate pair",
   724 bool Reader::decodeUnicodeEscapeSequence(Token& token,
   727                                          unsigned int& ret_unicode) {
   728   if (end - current < 4)
   730         "Bad unicode escape sequence in string: four digits expected.",
   734   for (
int index = 0; index < 4; ++index) {
   737     if (c >= 
'0' && c <= 
'9')
   739     else if (c >= 
'a' && c <= 
'f')
   740       unicode += c - 
'a' + 10;
   741     else if (c >= 
'A' && c <= 
'F')
   742       unicode += c - 
'A' + 10;
   745           "Bad unicode escape sequence in string: hexadecimal digit expected.",
   749   ret_unicode = 
static_cast<unsigned int>(unicode);
   757   info.message_ = message;
   759   errors_.push_back(info);
   763 bool Reader::recoverFromError(TokenType skipUntilToken) {
   764   size_t const errorCount = errors_.size();
   767     if (!readToken(skip))
   768       errors_.resize(errorCount); 
   769     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
   772   errors_.resize(errorCount);
   778                                 TokenType skipUntilToken) {
   779   addError(message, token);
   780   return recoverFromError(skipUntilToken);
   783 Value& Reader::currentValue() { 
return *(nodes_.top()); }
   786   if (current_ == end_)
   791 void Reader::getLocationLineAndColumn(
Location location,
   797   while (current < location && current != end_) {
   800       if (*current == 
'\n')
   802       lastLineStart = current;
   804     } 
else if (c == 
'\n') {
   805       lastLineStart = current;
   810   column = int(location - lastLineStart) + 1;
   816   getLocationLineAndColumn(location, line, column);
   817   char buffer[18 + 16 + 16 + 1];
   818   snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
   829   for (Errors::const_iterator itError = errors_.begin();
   830        itError != errors_.end();
   832     const ErrorInfo& error = *itError;
   834         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
   835     formattedMessage += 
"  " + error.message_ + 
"\n";
   838           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
   840   return formattedMessage;
   844   std::vector<Reader::StructuredError> allErrors;
   845   for (Errors::const_iterator itError = errors_.begin();
   846        itError != errors_.end();
   848     const ErrorInfo& error = *itError;
   852     structured.
message = error.message_;
   853     allErrors.push_back(structured);
   859   ptrdiff_t 
const length = end_ - begin_;
   864   token.type_ = tokenError;
   869   info.message_ = message;
   871   errors_.push_back(info);
   876   ptrdiff_t 
const length = end_ - begin_;
   882   token.type_ = tokenError;
   887   info.message_ = message;
   889   errors_.push_back(info);
   894   return !errors_.size();
   900   static OurFeatures all();
   903   bool allowDroppedNullPlaceholders_;
   904   bool allowNumericKeys_;
   905   bool allowSingleQuotes_;
   908   bool allowSpecialFloats_;
   915 OurFeatures OurFeatures::all() { 
return OurFeatures(); }
   926     ptrdiff_t offset_start;
   927     ptrdiff_t offset_limit;
   931   OurReader(OurFeatures 
const& features);
   932   bool parse(
const char* beginDoc,
   935              bool collectComments = 
true);
   943   OurReader(OurReader 
const&);  
   944   void operator=(OurReader 
const&);  
   947     tokenEndOfStream = 0,
   961     tokenMemberSeparator,
   980   typedef std::deque<ErrorInfo> Errors;
   982   bool readToken(Token& token);
   984   bool match(Location pattern, 
int patternLength);
   986   bool readCStyleComment();
   987   bool readCppStyleComment();
   989   bool readStringSingleQuote();
   990   bool readNumber(
bool checkInf);
   992   bool readObject(Token& token);
   993   bool readArray(Token& token);
   994   bool decodeNumber(Token& token);
   995   bool decodeNumber(Token& token, 
Value& decoded);
   996   bool decodeString(Token& token);
   998   bool decodeDouble(Token& token);
   999   bool decodeDouble(Token& token, 
Value& decoded);
  1000   bool decodeUnicodeCodePoint(Token& token,
  1003                               unsigned int& unicode);
  1004   bool decodeUnicodeEscapeSequence(Token& token,
  1007                                    unsigned int& unicode);
  1008   bool addError(
const JSONCPP_STRING& message, Token& token, Location extra = 0);
  1009   bool recoverFromError(TokenType skipUntilToken);
  1012                           TokenType skipUntilToken);
  1013   void skipUntilSpace();
  1014   Value& currentValue();
  1017   getLocationLineAndColumn(Location location, 
int& line, 
int& column) 
const;
  1018   JSONCPP_STRING getLocationLineAndColumn(Location location) 
const;
  1020   void skipCommentTokens(Token& token);
  1022   typedef std::stack<Value*> Nodes;
  1029   Location lastValueEnd_;
  1033   OurFeatures 
const features_;
  1034   bool collectComments_;
  1039 OurReader::OurReader(OurFeatures 
const& features)
  1040     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
  1041       lastValue_(), commentsBefore_(),
  1042       features_(features), collectComments_() {
  1045 bool OurReader::parse(
const char* beginDoc,
  1048                    bool collectComments) {
  1049   if (!features_.allowComments_) {
  1050     collectComments = 
false;
  1055   collectComments_ = collectComments;
  1059   commentsBefore_.clear();
  1061   while (!nodes_.empty())
  1065   bool successful = readValue();
  1067   skipCommentTokens(token);
  1068   if (features_.failIfExtra_) {
  1069     if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
  1070       addError(
"Extra non-whitespace after JSON value.", token);
  1074   if (collectComments_ && !commentsBefore_.empty())
  1076   if (features_.strictRoot_) {
  1080       token.type_ = tokenError;
  1081       token.start_ = beginDoc;
  1082       token.end_ = endDoc;
  1084           "A valid JSON document must be either an array or an object value.",
  1092 bool OurReader::readValue() {
  1094   if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError(
"Exceeded stackLimit in readValue().");
  1096   skipCommentTokens(token);
  1097   bool successful = 
true;
  1099   if (collectComments_ && !commentsBefore_.empty()) {
  1101     commentsBefore_.clear();
  1104   switch (token.type_) {
  1105   case tokenObjectBegin:
  1106     successful = readObject(token);
  1107     currentValue().setOffsetLimit(current_ - begin_);
  1109   case tokenArrayBegin:
  1110     successful = readArray(token);
  1111     currentValue().setOffsetLimit(current_ - begin_);
  1114     successful = decodeNumber(token);
  1117     successful = decodeString(token);
  1122     currentValue().swapPayload(v);
  1123     currentValue().setOffsetStart(token.start_ - begin_);
  1124     currentValue().setOffsetLimit(token.end_ - begin_);
  1130     currentValue().swapPayload(v);
  1131     currentValue().setOffsetStart(token.start_ - begin_);
  1132     currentValue().setOffsetLimit(token.end_ - begin_);
  1139     currentValue().setOffsetStart(token.start_ - begin_);
  1140     currentValue().setOffsetLimit(token.end_ - begin_);
  1145     Value v(std::numeric_limits<double>::quiet_NaN());
  1146     currentValue().swapPayload(v);
  1147     currentValue().setOffsetStart(token.start_ - begin_);
  1148     currentValue().setOffsetLimit(token.end_ - begin_);
  1153     Value v(std::numeric_limits<double>::infinity());
  1154     currentValue().swapPayload(v);
  1155     currentValue().setOffsetStart(token.start_ - begin_);
  1156     currentValue().setOffsetLimit(token.end_ - begin_);
  1161     Value v(-std::numeric_limits<double>::infinity());
  1162     currentValue().swapPayload(v);
  1163     currentValue().setOffsetStart(token.start_ - begin_);
  1164     currentValue().setOffsetLimit(token.end_ - begin_);
  1167   case tokenArraySeparator:
  1168   case tokenObjectEnd:
  1170     if (features_.allowDroppedNullPlaceholders_) {
  1176       currentValue().setOffsetStart(current_ - begin_ - 1);
  1177       currentValue().setOffsetLimit(current_ - begin_);
  1181     currentValue().setOffsetStart(token.start_ - begin_);
  1182     currentValue().setOffsetLimit(token.end_ - begin_);
  1183     return addError(
"Syntax error: value, object or array expected.", token);
  1186   if (collectComments_) {
  1187     lastValueEnd_ = current_;
  1188     lastValue_ = ¤tValue();
  1194 void OurReader::skipCommentTokens(Token& token) {
  1195   if (features_.allowComments_) {
  1198     } 
while (token.type_ == tokenComment);
  1204 bool OurReader::readToken(Token& token) {
  1206   token.start_ = current_;
  1207   Char c = getNextChar();
  1211     token.type_ = tokenObjectBegin;
  1214     token.type_ = tokenObjectEnd;
  1217     token.type_ = tokenArrayBegin;
  1220     token.type_ = tokenArrayEnd;
  1223     token.type_ = tokenString;
  1227     if (features_.allowSingleQuotes_) {
  1228     token.type_ = tokenString;
  1229     ok = readStringSingleQuote();
  1233     token.type_ = tokenComment;
  1246     token.type_ = tokenNumber;
  1250     if (readNumber(
true)) {
  1251       token.type_ = tokenNumber;
  1253       token.type_ = tokenNegInf;
  1254       ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
  1258     token.type_ = tokenTrue;
  1259     ok = match(
"rue", 3);
  1262     token.type_ = tokenFalse;
  1263     ok = match(
"alse", 4);
  1266     token.type_ = tokenNull;
  1267     ok = match(
"ull", 3);
  1270     if (features_.allowSpecialFloats_) {
  1271       token.type_ = tokenNaN;
  1272       ok = match(
"aN", 2);
  1278     if (features_.allowSpecialFloats_) {
  1279       token.type_ = tokenPosInf;
  1280       ok = match(
"nfinity", 7);
  1286     token.type_ = tokenArraySeparator;
  1289     token.type_ = tokenMemberSeparator;
  1292     token.type_ = tokenEndOfStream;
  1299     token.type_ = tokenError;
  1300   token.end_ = current_;
  1304 void OurReader::skipSpaces() {
  1305   while (current_ != end_) {
  1307     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
  1314 bool OurReader::match(
Location pattern, 
int patternLength) {
  1315   if (end_ - current_ < patternLength)
  1317   int index = patternLength;
  1319     if (current_[index] != pattern[index])
  1321   current_ += patternLength;
  1325 bool OurReader::readComment() {
  1326   Location commentBegin = current_ - 1;
  1327   Char c = getNextChar();
  1328   bool successful = 
false;
  1330     successful = readCStyleComment();
  1332     successful = readCppStyleComment();
  1336   if (collectComments_) {
  1343     addComment(commentBegin, current_, placement);
  1350   assert(collectComments_);
  1353     assert(lastValue_ != 0);
  1354     lastValue_->setComment(normalized, placement);
  1356     commentsBefore_ += normalized;
  1360 bool OurReader::readCStyleComment() {
  1361   while ((current_ + 1) < end_) {
  1362     Char c = getNextChar();
  1363     if (c == 
'*' && *current_ == 
'/')
  1366   return getNextChar() == 
'/';
  1369 bool OurReader::readCppStyleComment() {
  1370   while (current_ != end_) {
  1371     Char c = getNextChar();
  1376       if (current_ != end_ && *current_ == 
'\n')
  1385 bool OurReader::readNumber(
bool checkInf) {
  1386   const char *p = current_;
  1387   if (checkInf && p != end_ && *p == 
'I') {
  1393   while (c >= 
'0' && c <= 
'9')
  1394     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1397     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1398     while (c >= 
'0' && c <= 
'9')
  1399       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1402   if (c == 
'e' || c == 
'E') {
  1403     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1404     if (c == 
'+' || c == 
'-')
  1405       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1406     while (c >= 
'0' && c <= 
'9')
  1407       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1411 bool OurReader::readString() {
  1413   while (current_ != end_) {
  1424 bool OurReader::readStringSingleQuote() {
  1426   while (current_ != end_) {
  1436 bool OurReader::readObject(Token& tokenStart) {
  1440   currentValue().swapPayload(init);
  1441   currentValue().setOffsetStart(tokenStart.start_ - begin_);
  1442   while (readToken(tokenName)) {
  1443     bool initialTokenOk = 
true;
  1444     while (tokenName.type_ == tokenComment && initialTokenOk)
  1445       initialTokenOk = readToken(tokenName);
  1446     if (!initialTokenOk)
  1448     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
  1451     if (tokenName.type_ == tokenString) {
  1452       if (!decodeString(tokenName, name))
  1453         return recoverFromError(tokenObjectEnd);
  1454     } 
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
  1456       if (!decodeNumber(tokenName, numberName))
  1457         return recoverFromError(tokenObjectEnd);
  1464     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
  1465       return addErrorAndRecover(
  1466           "Missing ':' after object member name", colon, tokenObjectEnd);
  1468     if (name.length() >= (1U<<30)) throwRuntimeError(
"keylength >= 2^30");
  1469     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
  1471       return addErrorAndRecover(
  1472           msg, tokenName, tokenObjectEnd);
  1474     Value& value = currentValue()[name];
  1475     nodes_.push(&value);
  1476     bool ok = readValue();
  1479       return recoverFromError(tokenObjectEnd);
  1482     if (!readToken(comma) ||
  1483         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
  1484          comma.type_ != tokenComment)) {
  1485       return addErrorAndRecover(
  1486           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
  1488     bool finalizeTokenOk = 
true;
  1489     while (comma.type_ == tokenComment && finalizeTokenOk)
  1490       finalizeTokenOk = readToken(comma);
  1491     if (comma.type_ == tokenObjectEnd)
  1494   return addErrorAndRecover(
  1495       "Missing '}' or object member name", tokenName, tokenObjectEnd);
  1498 bool OurReader::readArray(Token& tokenStart) {
  1500   currentValue().swapPayload(init);
  1501   currentValue().setOffsetStart(tokenStart.start_ - begin_);
  1503   if (current_ != end_ && *current_ == 
']') 
  1506     readToken(endArray);
  1511     Value& value = currentValue()[index++];
  1512     nodes_.push(&value);
  1513     bool ok = readValue();
  1516       return recoverFromError(tokenArrayEnd);
  1520     ok = readToken(token);
  1521     while (token.type_ == tokenComment && ok) {
  1522       ok = readToken(token);
  1525         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
  1526     if (!ok || badTokenType) {
  1527       return addErrorAndRecover(
  1528           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
  1530     if (token.type_ == tokenArrayEnd)
  1536 bool OurReader::decodeNumber(Token& token) {
  1538   if (!decodeNumber(token, decoded))
  1541   currentValue().setOffsetStart(token.start_ - begin_);
  1542   currentValue().setOffsetLimit(token.end_ - begin_);
  1546 bool OurReader::decodeNumber(Token& token, 
Value& decoded) {
  1551   bool isNegative = *current == 
'-';
  1558   Value::LargestUInt threshold = maxIntegerValue / 10;
  1559   Value::LargestUInt value = 0;
  1560   while (current < token.end_) {
  1561     Char c = *current++;
  1562     if (c < '0' || c > 
'9')
  1563       return decodeDouble(token, decoded);
  1564     Value::UInt digit(static_cast<Value::UInt>(c - 
'0'));
  1565     if (value >= threshold) {
  1570       if (value > threshold || current != token.end_ ||
  1571           digit > maxIntegerValue % 10) {
  1572         return decodeDouble(token, decoded);
  1575     value = value * 10 + digit;
  1586 bool OurReader::decodeDouble(Token& token) {
  1588   if (!decodeDouble(token, decoded))
  1591   currentValue().setOffsetStart(token.start_ - begin_);
  1592   currentValue().setOffsetLimit(token.end_ - begin_);
  1596 bool OurReader::decodeDouble(Token& token, 
Value& decoded) {
  1598   const int bufferSize = 32;
  1600   ptrdiff_t 
const length = token.end_ - token.start_;
  1604     return addError(
"Unable to parse token length", token);
  1606   size_t const ulength = 
static_cast<size_t>(length);
  1613   char format[] = 
"%lf";
  1615   if (length <= bufferSize) {
  1616     Char buffer[bufferSize + 1];
  1617     memcpy(buffer, token.start_, ulength);
  1620     count = sscanf(buffer, format, &value);
  1623     count = sscanf(buffer.c_str(), format, &value);
  1628                         "' is not a number.",
  1634 bool OurReader::decodeString(Token& token) {
  1636   if (!decodeString(token, decoded_string))
  1638   Value decoded(decoded_string);
  1639   currentValue().swapPayload(decoded);
  1640   currentValue().setOffsetStart(token.start_ - begin_);
  1641   currentValue().setOffsetLimit(token.end_ - begin_);
  1645 bool OurReader::decodeString(Token& token, 
JSONCPP_STRING& decoded) {
  1646   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
  1647   Location current = token.start_ + 1; 
  1649   while (current != end) {
  1650     Char c = *current++;
  1653     else if (c == 
'\\') {
  1655         return addError(
"Empty escape sequence in string", token, current);
  1656       Char escape = *current++;
  1683         unsigned int unicode;
  1684         if (!decodeUnicodeCodePoint(token, current, end, unicode))
  1689         return addError(
"Bad escape sequence in string", token, current);
  1698 bool OurReader::decodeUnicodeCodePoint(Token& token,
  1701                                     unsigned int& unicode) {
  1703   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
  1705   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
  1707     if (end - current < 6)
  1709           "additional six characters expected to parse unicode surrogate pair.",
  1712     unsigned int surrogatePair;
  1713     if (*(current++) == 
'\\' && *(current++) == 
'u') {
  1714       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
  1715         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
  1719       return addError(
"expecting another \\u token to begin the second half of "  1720                       "a unicode surrogate pair",
  1727 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
  1730                                          unsigned int& ret_unicode) {
  1731   if (end - current < 4)
  1733         "Bad unicode escape sequence in string: four digits expected.",
  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.",
  1752   ret_unicode = 
static_cast<unsigned int>(unicode);
  1759   info.token_ = token;
  1760   info.message_ = message;
  1761   info.extra_ = extra;
  1762   errors_.push_back(info);
  1766 bool OurReader::recoverFromError(TokenType skipUntilToken) {
  1767   size_t errorCount = errors_.size();
  1770     if (!readToken(skip))
  1771       errors_.resize(errorCount); 
  1772     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
  1775   errors_.resize(errorCount);
  1779 bool OurReader::addErrorAndRecover(
const JSONCPP_STRING& message,
  1781                                 TokenType skipUntilToken) {
  1782   addError(message, token);
  1783   return recoverFromError(skipUntilToken);
  1786 Value& OurReader::currentValue() { 
return *(nodes_.top()); }
  1788 OurReader::Char OurReader::getNextChar() {
  1789   if (current_ == end_)
  1794 void OurReader::getLocationLineAndColumn(
Location location,
  1796                                       int& column)
 const {
  1800   while (current < location && current != end_) {
  1801     Char c = *current++;
  1803       if (*current == 
'\n')
  1805       lastLineStart = current;
  1807     } 
else if (c == 
'\n') {
  1808       lastLineStart = current;
  1813   column = int(location - lastLineStart) + 1;
  1819   getLocationLineAndColumn(location, line, column);
  1820   char buffer[18 + 16 + 16 + 1];
  1821   snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
  1827   for (Errors::const_iterator itError = errors_.begin();
  1828        itError != errors_.end();
  1830     const ErrorInfo& error = *itError;
  1832         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
  1833     formattedMessage += 
"  " + error.message_ + 
"\n";
  1836           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
  1838   return formattedMessage;
  1841 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
 const {
  1842   std::vector<OurReader::StructuredError> allErrors;
  1843   for (Errors::const_iterator itError = errors_.begin();
  1844        itError != errors_.end();
  1846     const ErrorInfo& error = *itError;
  1847     OurReader::StructuredError structured;
  1848     structured.offset_start = error.token_.start_ - begin_;
  1849     structured.offset_limit = error.token_.end_ - begin_;
  1850     structured.message = error.message_;
  1851     allErrors.push_back(structured);
  1857   ptrdiff_t length = end_ - begin_;
  1862   token.type_ = tokenError;
  1866   info.token_ = token;
  1867   info.message_ = message;
  1869   errors_.push_back(info);
  1874   ptrdiff_t length = end_ - begin_;
  1880   token.type_ = tokenError;
  1884   info.token_ = token;
  1885   info.message_ = message;
  1887   errors_.push_back(info);
  1891 bool OurReader::good()
 const {
  1892   return !errors_.size();
  1897   bool const collectComments_;
  1901     bool collectComments,
  1902     OurFeatures 
const& features)
  1903   : collectComments_(collectComments)
  1907       char const* beginDoc, 
char const* endDoc,
  1909     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
  1911       *errs = reader_.getFormattedErrorMessages();
  1919   setDefaults(&settings_);
  1925   bool collectComments = settings_[
"collectComments"].asBool();
  1926   OurFeatures features = OurFeatures::all();
  1927   features.allowComments_ = settings_[
"allowComments"].asBool();
  1928   features.strictRoot_ = settings_[
"strictRoot"].asBool();
  1929   features.allowDroppedNullPlaceholders_ = settings_[
"allowDroppedNullPlaceholders"].asBool();
  1930   features.allowNumericKeys_ = settings_[
"allowNumericKeys"].asBool();
  1931   features.allowSingleQuotes_ = settings_[
"allowSingleQuotes"].asBool();
  1932   features.stackLimit_ = settings_[
"stackLimit"].asInt();
  1933   features.failIfExtra_ = settings_[
"failIfExtra"].asBool();
  1934   features.rejectDupKeys_ = settings_[
"rejectDupKeys"].asBool();
  1935   features.allowSpecialFloats_ = settings_[
"allowSpecialFloats"].asBool();
  1936   return new OurCharReader(collectComments, features);
  1940   valid_keys->clear();
  1941   valid_keys->insert(
"collectComments");
  1942   valid_keys->insert(
"allowComments");
  1943   valid_keys->insert(
"strictRoot");
  1944   valid_keys->insert(
"allowDroppedNullPlaceholders");
  1945   valid_keys->insert(
"allowNumericKeys");
  1946   valid_keys->insert(
"allowSingleQuotes");
  1947   valid_keys->insert(
"stackLimit");
  1948   valid_keys->insert(
"failIfExtra");
  1949   valid_keys->insert(
"rejectDupKeys");
  1950   valid_keys->insert(
"allowSpecialFloats");
  1955   if (!invalid) invalid = &my_invalid;  
  1957   std::set<JSONCPP_STRING> valid_keys;
  1960   size_t n = keys.size();
  1961   for (
size_t i = 0; i < n; ++i) {
  1963     if (valid_keys.find(key) == valid_keys.end()) {
  1964       inv[key] = settings_[key];
  1967   return 0u == inv.
size();
  1971   return settings_[key];
  1977   (*settings)[
"allowComments"] = 
false;
  1978   (*settings)[
"strictRoot"] = 
true;
  1979   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
  1980   (*settings)[
"allowNumericKeys"] = 
false;
  1981   (*settings)[
"allowSingleQuotes"] = 
false;
  1982   (*settings)[
"stackLimit"] = 1000;
  1983   (*settings)[
"failIfExtra"] = 
true;
  1984   (*settings)[
"rejectDupKeys"] = 
true;
  1985   (*settings)[
"allowSpecialFloats"] = 
false;
  1992   (*settings)[
"collectComments"] = 
true;
  1993   (*settings)[
"allowComments"] = 
true;
  1994   (*settings)[
"strictRoot"] = 
false;
  1995   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
  1996   (*settings)[
"allowNumericKeys"] = 
false;
  1997   (*settings)[
"allowSingleQuotes"] = 
false;
  1998   (*settings)[
"stackLimit"] = 1000;
  1999   (*settings)[
"failIfExtra"] = 
false;
  2000   (*settings)[
"rejectDupKeys"] = 
false;
  2001   (*settings)[
"allowSpecialFloats"] = 
false;
  2013   ssin << sin.rdbuf();
  2015   char const* begin = doc.data();
  2016   char const* end = begin + doc.size();
  2019   return reader->parse(begin, end, root, errs);
  2028             "Error from reader: %s",
  2031     throwRuntimeError(errs);
 #define JSONCPP_OSTRINGSTREAM
std::vector< StructuredError > getStructuredErrors() const
Returns a vector of structured erros encounted while parsing. 
static void strictMode(Json::Value *settings)
Same as old Features::strictMode(). 
array value (ordered list) 
CharReader * newCharReader() const
Allocate a CharReader via operator new(). 
std::auto_ptr< CharReader > CharReaderPtr
bool parseFromStream(CharReader::Factory const &, std::istream &, Value *root, std::string *errs)
Consume entire stream and use its begin/end. 
object value (collection of name/value pairs). 
std::istream & operator>>(std::istream &, Value &)
Read from 'sin' into 'root'. 
void swapPayload(Value &other)
Swap values but leave comments and source offsets in place. 
Value & operator[](std::string key)
A simple way to update a specific setting. 
static JSONCPP_STRING codePointToUTF8(unsigned int cp)
Converts a unicode code-point to UTF-8. 
static const Int maxInt
Maximum signed int value that can be stored in a Json::Value. 
ptrdiff_t getOffsetStart() const
Json::LargestUInt LargestUInt
Features()
Initialize the configuration like JsonConfig::allFeatures;. 
std::string getFormatedErrorMessages() const
Returns a user friendly string that list errors in the parsed document. 
An error tagged with where in the JSON text it was encountered. 
void setComment(const char *comment, CommentPlacement placement)
static const LargestInt minLargestInt
Minimum signed integer value that can be stored in a Json::Value. 
bool allowComments_
true if comments are allowed. Default: true. 
static void fixNumericLocaleInput(char *begin, char *end)
bool allowNumericKeys_
true if numeric object key are allowed. Default: false. 
static size_t const stackLimit_g
ArrayIndex size() const
Number of values in array or object. 
const char * asCString() const
Embedded zeroes could cause you trouble! 
bool parse(const std::string &document, Value &root, bool collectComments=true)
Read a Value from a JSON document. 
std::string asString() const
Embedded zeroes are possible. 
JSON (JavaScript Object Notation). 
bool allowDroppedNullPlaceholders_
true if dropped null placeholders are allowed. Default: false. 
Json::LargestInt LargestInt
ptrdiff_t getOffsetLimit() const
bool good() const
Return whether there are any errors. 
static void setDefaults(Json::Value *settings)
Called by ctor, but you can use this to reset settings_. 
bool validate(Json::Value *invalid) const
Interface for reading JSON from a char array. 
std::string getFormattedErrorMessages() const
Returns a user friendly string that list errors in the parsed document. 
void setOffsetStart(ptrdiff_t start)
#define JSONCPP_ISTRINGSTREAM
static Features all()
A configuration that allows all features and assumes all strings are UTF-8. 
static std::string normalizeEOL(Reader::Location begin, Reader::Location end)
a comment on the line after a value (only make sense for 
bool pushError(const Value &value, const std::string &message)
Add a semantic error message. 
#define JSONCPP_DEPRECATED_STACK_LIMIT
void setOffsetLimit(ptrdiff_t limit)
std::vector< std::string > Members
static Features strictMode()
A configuration that is strictly compatible with the JSON specification. 
bool strictRoot_
true if root must be either an array or an object value. 
Build a CharReader implementation. 
static void getValidReaderKeys(std::set< std::string > *valid_keys)
static bool containsNewLine(Reader::Location begin, Reader::Location end)
Configuration passed to reader and writer. 
virtual CharReader * newCharReader() const =0
Allocate a CharReader via operator new(). 
a comment placed on the line before a value 
Reader()
Constructs a Reader allowing all features for parsing. 
a comment just after a value on the same line 
static const LargestInt maxLargestInt
Maximum signed integer value that can be stored in a Json::Value. 
static const LargestUInt maxLargestUInt
Maximum unsigned integer value that can be stored in a Json::Value.