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   document_.assign(document.begin(), document.end());
   107   const char* begin = document_.c_str();
   108   const char* end = begin + document_.length();
   109   return parse(begin, end, root, collectComments);
   121   std::getline(sin, doc, (
char)EOF);
   122   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
   128                    bool collectComments) {
   130     collectComments = 
false;
   135   collectComments_ = collectComments;
   139   commentsBefore_.clear();
   141   while (!nodes_.empty())
   145   bool successful = readValue();
   147   skipCommentTokens(token);
   148   if (collectComments_ && !commentsBefore_.empty())
   154       token.type_ = tokenError;
   155       token.start_ = beginDoc;
   158           "A valid JSON document must be either an array or an object value.",
   166 bool Reader::readValue() {
   170   if (nodes_.size() > 
stackLimit_g) throwRuntimeError(
"Exceeded stackLimit in readValue().");
   173   skipCommentTokens(token);
   174   bool successful = 
true;
   176   if (collectComments_ && !commentsBefore_.empty()) {
   178     commentsBefore_.clear();
   181   switch (token.type_) {
   182   case tokenObjectBegin:
   183     successful = readObject(token);
   186   case tokenArrayBegin:
   187     successful = readArray(token);
   191     successful = decodeNumber(token);
   194     successful = decodeString(token);
   220   case tokenArraySeparator:
   236     return addError(
"Syntax error: value, object or array expected.", token);
   239   if (collectComments_) {
   240     lastValueEnd_ = current_;
   241     lastValue_ = ¤tValue();
   247 void Reader::skipCommentTokens(Token& token) {
   251     } 
while (token.type_ == tokenComment);
   257 bool Reader::readToken(Token& token) {
   259   token.start_ = current_;
   260   Char c = getNextChar();
   264     token.type_ = tokenObjectBegin;
   267     token.type_ = tokenObjectEnd;
   270     token.type_ = tokenArrayBegin;
   273     token.type_ = tokenArrayEnd;
   276     token.type_ = tokenString;
   280     token.type_ = tokenComment;
   294     token.type_ = tokenNumber;
   298     token.type_ = tokenTrue;
   299     ok = match(
"rue", 3);
   302     token.type_ = tokenFalse;
   303     ok = match(
"alse", 4);
   306     token.type_ = tokenNull;
   307     ok = match(
"ull", 3);
   310     token.type_ = tokenArraySeparator;
   313     token.type_ = tokenMemberSeparator;
   316     token.type_ = tokenEndOfStream;
   323     token.type_ = tokenError;
   324   token.end_ = current_;
   328 void Reader::skipSpaces() {
   329   while (current_ != end_) {
   331     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
   338 bool Reader::match(Location pattern, 
int patternLength) {
   339   if (end_ - current_ < patternLength)
   341   int index = patternLength;
   343     if (current_[index] != pattern[index])
   345   current_ += patternLength;
   349 bool Reader::readComment() {
   350   Location commentBegin = current_ - 1;
   351   Char c = getNextChar();
   352   bool successful = 
false;
   354     successful = readCStyleComment();
   356     successful = readCppStyleComment();
   360   if (collectComments_) {
   362     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
   363       if (c != 
'*' || !containsNewLine(commentBegin, current_))
   367     addComment(commentBegin, current_, placement);
   374   normalized.reserve(static_cast<size_t>(end - begin));
   376   while (current != end) {
   379       if (current != end && *current == 
'\n')
   392 Reader::addComment(Location begin, Location end, 
CommentPlacement placement) {
   393   assert(collectComments_);
   396     assert(lastValue_ != 0);
   397     lastValue_->
setComment(normalized, placement);
   399     commentsBefore_ += normalized;
   403 bool Reader::readCStyleComment() {
   404   while ((current_ + 1) < end_) {
   405     Char c = getNextChar();
   406     if (c == 
'*' && *current_ == 
'/')
   409   return getNextChar() == 
'/';
   412 bool Reader::readCppStyleComment() {
   413   while (current_ != end_) {
   414     Char c = getNextChar();
   419       if (current_ != end_ && *current_ == 
'\n')
   428 void Reader::readNumber() {
   429   const char *p = current_;
   432   while (c >= 
'0' && c <= 
'9')
   433     c = (current_ = p) < end_ ? *p++ : 
'\0';
   436     c = (current_ = p) < end_ ? *p++ : 
'\0';
   437     while (c >= 
'0' && c <= 
'9')
   438       c = (current_ = p) < end_ ? *p++ : 
'\0';
   441   if (c == 
'e' || c == 
'E') {
   442     c = (current_ = p) < end_ ? *p++ : 
'\0';
   443     if (c == 
'+' || c == 
'-')
   444       c = (current_ = p) < end_ ? *p++ : 
'\0';
   445     while (c >= 
'0' && c <= 
'9')
   446       c = (current_ = p) < end_ ? *p++ : 
'\0';
   450 bool Reader::readString() {
   452   while (current_ != end_) {
   462 bool Reader::readObject(Token& tokenStart) {
   468   while (readToken(tokenName)) {
   469     bool initialTokenOk = 
true;
   470     while (tokenName.type_ == tokenComment && initialTokenOk)
   471       initialTokenOk = readToken(tokenName);
   474     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
   477     if (tokenName.type_ == tokenString) {
   478       if (!decodeString(tokenName, name))
   479         return recoverFromError(tokenObjectEnd);
   482       if (!decodeNumber(tokenName, numberName))
   483         return recoverFromError(tokenObjectEnd);
   490     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
   491       return addErrorAndRecover(
   492           "Missing ':' after object member name", colon, tokenObjectEnd);
   494     Value& value = currentValue()[name];
   496     bool ok = readValue();
   499       return recoverFromError(tokenObjectEnd);
   502     if (!readToken(comma) ||
   503         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
   504          comma.type_ != tokenComment)) {
   505       return addErrorAndRecover(
   506           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
   508     bool finalizeTokenOk = 
true;
   509     while (comma.type_ == tokenComment && finalizeTokenOk)
   510       finalizeTokenOk = readToken(comma);
   511     if (comma.type_ == tokenObjectEnd)
   514   return addErrorAndRecover(
   515       "Missing '}' or object member name", tokenName, tokenObjectEnd);
   518 bool Reader::readArray(Token& tokenStart) {
   523   if (current_ != end_ && *current_ == 
']') 
   531     Value& value = currentValue()[index++];
   533     bool ok = readValue();
   536       return recoverFromError(tokenArrayEnd);
   540     ok = readToken(token);
   541     while (token.type_ == tokenComment && ok) {
   542       ok = readToken(token);
   545         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
   546     if (!ok || badTokenType) {
   547       return addErrorAndRecover(
   548           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
   550     if (token.type_ == tokenArrayEnd)
   556 bool Reader::decodeNumber(Token& token) {
   558   if (!decodeNumber(token, decoded))
   566 bool Reader::decodeNumber(Token& token, Value& decoded) {
   571   bool isNegative = *current == 
'-';
   580   while (current < token.end_) {
   582     if (c < '0' || c > 
'9')
   583       return decodeDouble(token, decoded);
   584     Value::UInt digit(static_cast<Value::UInt>(c - 
'0'));
   585     if (value >= threshold) {
   590       if (value > threshold || current != token.end_ ||
   591           digit > maxIntegerValue % 10) {
   592         return decodeDouble(token, decoded);
   595     value = value * 10 + digit;
   597   if (isNegative && value == maxIntegerValue)
   608 bool Reader::decodeDouble(Token& token) {
   610   if (!decodeDouble(token, decoded))
   618 bool Reader::decodeDouble(Token& token, Value& decoded) {
   624                         "' is not a number.",
   630 bool Reader::decodeString(Token& token) {
   632   if (!decodeString(token, decoded_string))
   634   Value decoded(decoded_string);
   641 bool Reader::decodeString(Token& token, 
JSONCPP_STRING& decoded) {
   642   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
   643   Location current = token.start_ + 1; 
   645   while (current != end) {
   649     else if (c == 
'\\') {
   651         return addError(
"Empty escape sequence in string", token, current);
   652       Char escape = *current++;
   679         unsigned int unicode;
   680         if (!decodeUnicodeCodePoint(token, current, end, unicode))
   685         return addError(
"Bad escape sequence in string", token, current);
   694 bool Reader::decodeUnicodeCodePoint(Token& token,
   697                                     unsigned int& unicode) {
   699   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
   701   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
   703     if (end - current < 6)
   705           "additional six characters expected to parse unicode surrogate pair.",
   708     unsigned int surrogatePair;
   709     if (*(current++) == 
'\\' && *(current++) == 
'u') {
   710       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
   711         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
   715       return addError(
"expecting another \\u token to begin the second half of "   716                       "a unicode surrogate pair",
   723 bool Reader::decodeUnicodeEscapeSequence(Token& token,
   726                                          unsigned int& ret_unicode) {
   727   if (end - current < 4)
   729         "Bad unicode escape sequence in string: four digits expected.",
   733   for (
int index = 0; index < 4; ++index) {
   736     if (c >= 
'0' && c <= 
'9')
   738     else if (c >= 
'a' && c <= 
'f')
   739       unicode += c - 
'a' + 10;
   740     else if (c >= 
'A' && c <= 
'F')
   741       unicode += c - 
'A' + 10;
   744           "Bad unicode escape sequence in string: hexadecimal digit expected.",
   748   ret_unicode = 
static_cast<unsigned int>(unicode);
   753 Reader::addError(
const JSONCPP_STRING& message, Token& token, Location extra) {
   756   info.message_ = message;
   758   errors_.push_back(info);
   762 bool Reader::recoverFromError(TokenType skipUntilToken) {
   763   size_t const errorCount = errors_.size();
   766     if (!readToken(skip))
   767       errors_.resize(errorCount); 
   768     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
   771   errors_.resize(errorCount);
   777                                 TokenType skipUntilToken) {
   778   addError(message, token);
   779   return recoverFromError(skipUntilToken);
   782 Value& Reader::currentValue() { 
return *(nodes_.top()); }
   785   if (current_ == end_)
   790 void Reader::getLocationLineAndColumn(Location location,
   796   while (current < location && current != end_) {
   799       if (*current == 
'\n')
   801       lastLineStart = current;
   803     } 
else if (c == 
'\n') {
   804       lastLineStart = current;
   809   column = int(location - lastLineStart) + 1;
   813 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location)
 const {
   815   getLocationLineAndColumn(location, line, column);
   816   char buffer[18 + 16 + 16 + 1];
   817   snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
   828   for (Errors::const_iterator itError = errors_.begin();
   829        itError != errors_.end();
   831     const ErrorInfo& error = *itError;
   833         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
   834     formattedMessage += 
"  " + error.message_ + 
"\n";
   837           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
   839   return formattedMessage;
   843   std::vector<Reader::StructuredError> allErrors;
   844   for (Errors::const_iterator itError = errors_.begin();
   845        itError != errors_.end();
   847     const ErrorInfo& error = *itError;
   851     structured.
message = error.message_;
   852     allErrors.push_back(structured);
   858   ptrdiff_t 
const length = end_ - begin_;
   863   token.type_ = tokenError;
   868   info.message_ = message;
   870   errors_.push_back(info);
   875   ptrdiff_t 
const length = end_ - begin_;
   881   token.type_ = tokenError;
   886   info.message_ = message;
   888   errors_.push_back(info);
   893   return !errors_.size();
   899   static OurFeatures all();
   902   bool allowDroppedNullPlaceholders_;
   903   bool allowNumericKeys_;
   904   bool allowSingleQuotes_;
   907   bool allowSpecialFloats_;
   914 OurFeatures OurFeatures::all() { 
return OurFeatures(); }
   923   typedef const Char* Location;
   924   struct StructuredError {
   925     ptrdiff_t offset_start;
   926     ptrdiff_t offset_limit;
   930   OurReader(OurFeatures 
const& features);
   931   bool parse(
const char* beginDoc,
   934              bool collectComments = 
true);
   936   std::vector<StructuredError> getStructuredErrors() 
const;
   937   bool pushError(
const Value& value, 
const JSONCPP_STRING& message);
   938   bool pushError(
const Value& value, 
const JSONCPP_STRING& message, 
const Value& extra);
   942   OurReader(OurReader 
const&);  
   943   void operator=(OurReader 
const&);  
   946     tokenEndOfStream = 0,
   960     tokenMemberSeparator,
   979   typedef std::deque<ErrorInfo> Errors;
   981   bool readToken(Token& token);
   983   bool match(Location pattern, 
int patternLength);
   985   bool readCStyleComment();
   986   bool readCppStyleComment();
   988   bool readStringSingleQuote();
   989   bool readNumber(
bool checkInf);
   991   bool readObject(Token& token);
   992   bool readArray(Token& token);
   993   bool decodeNumber(Token& token);
   994   bool decodeNumber(Token& token, Value& decoded);
   995   bool decodeString(Token& token);
   997   bool decodeDouble(Token& token);
   998   bool decodeDouble(Token& token, Value& decoded);
   999   bool decodeUnicodeCodePoint(Token& token,
  1002                               unsigned int& unicode);
  1003   bool decodeUnicodeEscapeSequence(Token& token,
  1006                                    unsigned int& unicode);
  1007   bool addError(
const JSONCPP_STRING& message, Token& token, Location extra = 0);
  1008   bool recoverFromError(TokenType skipUntilToken);
  1011                           TokenType skipUntilToken);
  1012   void skipUntilSpace();
  1013   Value& currentValue();
  1016   getLocationLineAndColumn(Location location, 
int& line, 
int& column) 
const;
  1017   JSONCPP_STRING getLocationLineAndColumn(Location location) 
const;
  1019   void skipCommentTokens(Token& token);
  1021   static JSONCPP_STRING normalizeEOL(Location begin, Location end);
  1022   static bool containsNewLine(Location begin, Location end);
  1024   typedef std::stack<Value*> Nodes;
  1031   Location lastValueEnd_;
  1035   OurFeatures 
const features_;
  1036   bool collectComments_;
  1041 bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
  1042   for (; begin < end; ++begin)
  1043     if (*begin == 
'\n' || *begin == 
'\r')
  1048 OurReader::OurReader(OurFeatures 
const& features)
  1049     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
  1050       lastValue_(), commentsBefore_(),
  1051       features_(features), collectComments_() {
  1054 bool OurReader::parse(
const char* beginDoc,
  1057                    bool collectComments) {
  1058   if (!features_.allowComments_) {
  1059     collectComments = 
false;
  1064   collectComments_ = collectComments;
  1068   commentsBefore_.clear();
  1070   while (!nodes_.empty())
  1074   bool successful = readValue();
  1076   skipCommentTokens(token);
  1077   if (features_.failIfExtra_) {
  1078     if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
  1079       addError(
"Extra non-whitespace after JSON value.", token);
  1083   if (collectComments_ && !commentsBefore_.empty())
  1085   if (features_.strictRoot_) {
  1086     if (!root.isArray() && !root.isObject()) {
  1089       token.type_ = tokenError;
  1090       token.start_ = beginDoc;
  1091       token.end_ = endDoc;
  1093           "A valid JSON document must be either an array or an object value.",
  1101 bool OurReader::readValue() {
  1103   if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError(
"Exceeded stackLimit in readValue().");
  1105   skipCommentTokens(token);
  1106   bool successful = 
true;
  1108   if (collectComments_ && !commentsBefore_.empty()) {
  1110     commentsBefore_.clear();
  1113   switch (token.type_) {
  1114   case tokenObjectBegin:
  1115     successful = readObject(token);
  1116     currentValue().setOffsetLimit(current_ - begin_);
  1118   case tokenArrayBegin:
  1119     successful = readArray(token);
  1120     currentValue().setOffsetLimit(current_ - begin_);
  1123     successful = decodeNumber(token);
  1126     successful = decodeString(token);
  1131     currentValue().swapPayload(v);
  1132     currentValue().setOffsetStart(token.start_ - begin_);
  1133     currentValue().setOffsetLimit(token.end_ - begin_);
  1139     currentValue().swapPayload(v);
  1140     currentValue().setOffsetStart(token.start_ - begin_);
  1141     currentValue().setOffsetLimit(token.end_ - begin_);
  1147     currentValue().swapPayload(v);
  1148     currentValue().setOffsetStart(token.start_ - begin_);
  1149     currentValue().setOffsetLimit(token.end_ - begin_);
  1154     Value v(std::numeric_limits<double>::quiet_NaN());
  1155     currentValue().swapPayload(v);
  1156     currentValue().setOffsetStart(token.start_ - begin_);
  1157     currentValue().setOffsetLimit(token.end_ - begin_);
  1162     Value v(std::numeric_limits<double>::infinity());
  1163     currentValue().swapPayload(v);
  1164     currentValue().setOffsetStart(token.start_ - begin_);
  1165     currentValue().setOffsetLimit(token.end_ - begin_);
  1170     Value v(-std::numeric_limits<double>::infinity());
  1171     currentValue().swapPayload(v);
  1172     currentValue().setOffsetStart(token.start_ - begin_);
  1173     currentValue().setOffsetLimit(token.end_ - begin_);
  1176   case tokenArraySeparator:
  1177   case tokenObjectEnd:
  1179     if (features_.allowDroppedNullPlaceholders_) {
  1184       currentValue().swapPayload(v);
  1185       currentValue().setOffsetStart(current_ - begin_ - 1);
  1186       currentValue().setOffsetLimit(current_ - begin_);
  1190     currentValue().setOffsetStart(token.start_ - begin_);
  1191     currentValue().setOffsetLimit(token.end_ - begin_);
  1192     return addError(
"Syntax error: value, object or array expected.", token);
  1195   if (collectComments_) {
  1196     lastValueEnd_ = current_;
  1197     lastValue_ = ¤tValue();
  1203 void OurReader::skipCommentTokens(Token& token) {
  1204   if (features_.allowComments_) {
  1207     } 
while (token.type_ == tokenComment);
  1213 bool OurReader::readToken(Token& token) {
  1215   token.start_ = current_;
  1216   Char c = getNextChar();
  1220     token.type_ = tokenObjectBegin;
  1223     token.type_ = tokenObjectEnd;
  1226     token.type_ = tokenArrayBegin;
  1229     token.type_ = tokenArrayEnd;
  1232     token.type_ = tokenString;
  1236     if (features_.allowSingleQuotes_) {
  1237     token.type_ = tokenString;
  1238     ok = readStringSingleQuote();
  1242     token.type_ = tokenComment;
  1255     token.type_ = tokenNumber;
  1259     if (readNumber(
true)) {
  1260       token.type_ = tokenNumber;
  1262       token.type_ = tokenNegInf;
  1263       ok = features_.allowSpecialFloats_ && match(
"nfinity", 7);
  1267     token.type_ = tokenTrue;
  1268     ok = match(
"rue", 3);
  1271     token.type_ = tokenFalse;
  1272     ok = match(
"alse", 4);
  1275     token.type_ = tokenNull;
  1276     ok = match(
"ull", 3);
  1279     if (features_.allowSpecialFloats_) {
  1280       token.type_ = tokenNaN;
  1281       ok = match(
"aN", 2);
  1287     if (features_.allowSpecialFloats_) {
  1288       token.type_ = tokenPosInf;
  1289       ok = match(
"nfinity", 7);
  1295     token.type_ = tokenArraySeparator;
  1298     token.type_ = tokenMemberSeparator;
  1301     token.type_ = tokenEndOfStream;
  1308     token.type_ = tokenError;
  1309   token.end_ = current_;
  1313 void OurReader::skipSpaces() {
  1314   while (current_ != end_) {
  1316     if (c == 
' ' || c == 
'\t' || c == 
'\r' || c == 
'\n')
  1323 bool OurReader::match(Location pattern, 
int patternLength) {
  1324   if (end_ - current_ < patternLength)
  1326   int index = patternLength;
  1328     if (current_[index] != pattern[index])
  1330   current_ += patternLength;
  1334 bool OurReader::readComment() {
  1335   Location commentBegin = current_ - 1;
  1336   Char c = getNextChar();
  1337   bool successful = 
false;
  1339     successful = readCStyleComment();
  1341     successful = readCppStyleComment();
  1345   if (collectComments_) {
  1347     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
  1348       if (c != 
'*' || !containsNewLine(commentBegin, current_))
  1352     addComment(commentBegin, current_, placement);
  1357 JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
  1359   normalized.reserve(static_cast<size_t>(end - begin));
  1360   OurReader::Location current = begin;
  1361   while (current != end) {
  1362     char c = *current++;
  1364       if (current != end && *current == 
'\n')
  1377 OurReader::addComment(Location begin, Location end, 
CommentPlacement placement) {
  1378   assert(collectComments_);
  1381     assert(lastValue_ != 0);
  1382     lastValue_->setComment(normalized, placement);
  1384     commentsBefore_ += normalized;
  1388 bool OurReader::readCStyleComment() {
  1389   while ((current_ + 1) < end_) {
  1390     Char c = getNextChar();
  1391     if (c == 
'*' && *current_ == 
'/')
  1394   return getNextChar() == 
'/';
  1397 bool OurReader::readCppStyleComment() {
  1398   while (current_ != end_) {
  1399     Char c = getNextChar();
  1404       if (current_ != end_ && *current_ == 
'\n')
  1413 bool OurReader::readNumber(
bool checkInf) {
  1414   const char *p = current_;
  1415   if (checkInf && p != end_ && *p == 
'I') {
  1421   while (c >= 
'0' && c <= 
'9')
  1422     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1425     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1426     while (c >= 
'0' && c <= 
'9')
  1427       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1430   if (c == 
'e' || c == 
'E') {
  1431     c = (current_ = p) < end_ ? *p++ : 
'\0';
  1432     if (c == 
'+' || c == 
'-')
  1433       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1434     while (c >= 
'0' && c <= 
'9')
  1435       c = (current_ = p) < end_ ? *p++ : 
'\0';
  1439 bool OurReader::readString() {
  1441   while (current_ != end_) {
  1452 bool OurReader::readStringSingleQuote() {
  1454   while (current_ != end_) {
  1464 bool OurReader::readObject(Token& tokenStart) {
  1468   currentValue().swapPayload(init);
  1469   currentValue().setOffsetStart(tokenStart.start_ - begin_);
  1470   while (readToken(tokenName)) {
  1471     bool initialTokenOk = 
true;
  1472     while (tokenName.type_ == tokenComment && initialTokenOk)
  1473       initialTokenOk = readToken(tokenName);
  1474     if (!initialTokenOk)
  1476     if (tokenName.type_ == tokenObjectEnd && name.empty()) 
  1479     if (tokenName.type_ == tokenString) {
  1480       if (!decodeString(tokenName, name))
  1481         return recoverFromError(tokenObjectEnd);
  1482     } 
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
  1484       if (!decodeNumber(tokenName, numberName))
  1485         return recoverFromError(tokenObjectEnd);
  1486       name = numberName.asString();
  1492     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
  1493       return addErrorAndRecover(
  1494           "Missing ':' after object member name", colon, tokenObjectEnd);
  1496     if (name.length() >= (1U<<30)) throwRuntimeError(
"keylength >= 2^30");
  1497     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
  1499       return addErrorAndRecover(
  1500           msg, tokenName, tokenObjectEnd);
  1502     Value& value = currentValue()[name];
  1503     nodes_.push(&value);
  1504     bool ok = readValue();
  1507       return recoverFromError(tokenObjectEnd);
  1510     if (!readToken(comma) ||
  1511         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
  1512          comma.type_ != tokenComment)) {
  1513       return addErrorAndRecover(
  1514           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
  1516     bool finalizeTokenOk = 
true;
  1517     while (comma.type_ == tokenComment && finalizeTokenOk)
  1518       finalizeTokenOk = readToken(comma);
  1519     if (comma.type_ == tokenObjectEnd)
  1522   return addErrorAndRecover(
  1523       "Missing '}' or object member name", tokenName, tokenObjectEnd);
  1526 bool OurReader::readArray(Token& tokenStart) {
  1528   currentValue().swapPayload(init);
  1529   currentValue().setOffsetStart(tokenStart.start_ - begin_);
  1531   if (current_ != end_ && *current_ == 
']') 
  1534     readToken(endArray);
  1539     Value& value = currentValue()[index++];
  1540     nodes_.push(&value);
  1541     bool ok = readValue();
  1544       return recoverFromError(tokenArrayEnd);
  1548     ok = readToken(token);
  1549     while (token.type_ == tokenComment && ok) {
  1550       ok = readToken(token);
  1553         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
  1554     if (!ok || badTokenType) {
  1555       return addErrorAndRecover(
  1556           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
  1558     if (token.type_ == tokenArrayEnd)
  1564 bool OurReader::decodeNumber(Token& token) {
  1566   if (!decodeNumber(token, decoded))
  1568   currentValue().swapPayload(decoded);
  1569   currentValue().setOffsetStart(token.start_ - begin_);
  1570   currentValue().setOffsetLimit(token.end_ - begin_);
  1574 bool OurReader::decodeNumber(Token& token, Value& decoded) {
  1578   Location current = token.start_;
  1579   bool isNegative = *current == 
'-';
  1585                  : Value::maxLargestUInt;
  1588   while (current < token.end_) {
  1589     Char c = *current++;
  1590     if (c < '0' || c > 
'9')
  1591       return decodeDouble(token, decoded);
  1592     Value::UInt digit(static_cast<Value::UInt>(c - 
'0'));
  1593     if (value >= threshold) {
  1598       if (value > threshold || current != token.end_ ||
  1599           digit > maxIntegerValue % 10) {
  1600         return decodeDouble(token, decoded);
  1603     value = value * 10 + digit;
  1614 bool OurReader::decodeDouble(Token& token) {
  1616   if (!decodeDouble(token, decoded))
  1618   currentValue().swapPayload(decoded);
  1619   currentValue().setOffsetStart(token.start_ - begin_);
  1620   currentValue().setOffsetLimit(token.end_ - begin_);
  1624 bool OurReader::decodeDouble(Token& token, Value& decoded) {
  1626   const int bufferSize = 32;
  1628   ptrdiff_t 
const length = token.end_ - token.start_;
  1632     return addError(
"Unable to parse token length", token);
  1634   size_t const ulength = 
static_cast<size_t>(length);
  1641   char format[] = 
"%lf";
  1643   if (length <= bufferSize) {
  1644     Char buffer[bufferSize + 1];
  1645     memcpy(buffer, token.start_, ulength);
  1648     count = sscanf(buffer, format, &value);
  1651     count = sscanf(buffer.c_str(), format, &value);
  1656                         "' is not a number.",
  1662 bool OurReader::decodeString(Token& token) {
  1664   if (!decodeString(token, decoded_string))
  1666   Value decoded(decoded_string);
  1667   currentValue().swapPayload(decoded);
  1668   currentValue().setOffsetStart(token.start_ - begin_);
  1669   currentValue().setOffsetLimit(token.end_ - begin_);
  1673 bool OurReader::decodeString(Token& token, 
JSONCPP_STRING& decoded) {
  1674   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
  1675   Location current = token.start_ + 1; 
  1676   Location end = token.end_ - 1;       
  1677   while (current != end) {
  1678     Char c = *current++;
  1681     else if (c == 
'\\') {
  1683         return addError(
"Empty escape sequence in string", token, current);
  1684       Char escape = *current++;
  1711         unsigned int unicode;
  1712         if (!decodeUnicodeCodePoint(token, current, end, unicode))
  1717         return addError(
"Bad escape sequence in string", token, current);
  1726 bool OurReader::decodeUnicodeCodePoint(Token& token,
  1729                                     unsigned int& unicode) {
  1731   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
  1733   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
  1735     if (end - current < 6)
  1737           "additional six characters expected to parse unicode surrogate pair.",
  1740     unsigned int surrogatePair;
  1741     if (*(current++) == 
'\\' && *(current++) == 
'u') {
  1742       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
  1743         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
  1747       return addError(
"expecting another \\u token to begin the second half of "  1748                       "a unicode surrogate pair",
  1755 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
  1758                                          unsigned int& ret_unicode) {
  1759   if (end - current < 4)
  1761         "Bad unicode escape sequence in string: four digits expected.",
  1765   for (
int index = 0; index < 4; ++index) {
  1766     Char c = *current++;
  1768     if (c >= 
'0' && c <= 
'9')
  1770     else if (c >= 
'a' && c <= 
'f')
  1771       unicode += c - 
'a' + 10;
  1772     else if (c >= 
'A' && c <= 
'F')
  1773       unicode += c - 
'A' + 10;
  1776           "Bad unicode escape sequence in string: hexadecimal digit expected.",
  1780   ret_unicode = 
static_cast<unsigned int>(unicode);
  1785 OurReader::addError(
const JSONCPP_STRING& message, Token& token, Location extra) {
  1787   info.token_ = token;
  1788   info.message_ = message;
  1789   info.extra_ = extra;
  1790   errors_.push_back(info);
  1794 bool OurReader::recoverFromError(TokenType skipUntilToken) {
  1795   size_t errorCount = errors_.size();
  1798     if (!readToken(skip))
  1799       errors_.resize(errorCount); 
  1800     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
  1803   errors_.resize(errorCount);
  1807 bool OurReader::addErrorAndRecover(
const JSONCPP_STRING& message,
  1809                                 TokenType skipUntilToken) {
  1810   addError(message, token);
  1811   return recoverFromError(skipUntilToken);
  1814 Value& OurReader::currentValue() { 
return *(nodes_.top()); }
  1816 OurReader::Char OurReader::getNextChar() {
  1817   if (current_ == end_)
  1822 void OurReader::getLocationLineAndColumn(Location location,
  1824                                       int& column)
 const {
  1825   Location current = begin_;
  1826   Location lastLineStart = current;
  1828   while (current < location && current != end_) {
  1829     Char c = *current++;
  1831       if (*current == 
'\n')
  1833       lastLineStart = current;
  1835     } 
else if (c == 
'\n') {
  1836       lastLineStart = current;
  1841   column = int(location - lastLineStart) + 1;
  1845 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location)
 const {
  1847   getLocationLineAndColumn(location, line, column);
  1848   char buffer[18 + 16 + 16 + 1];
  1849   snprintf(buffer, 
sizeof(buffer), 
"Line %d, Column %d", line, column);
  1855   for (Errors::const_iterator itError = errors_.begin();
  1856        itError != errors_.end();
  1858     const ErrorInfo& error = *itError;
  1860         "* " + getLocationLineAndColumn(error.token_.start_) + 
"\n";
  1861     formattedMessage += 
"  " + error.message_ + 
"\n";
  1864           "See " + getLocationLineAndColumn(error.extra_) + 
" for detail.\n";
  1866   return formattedMessage;
  1869 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors()
 const {
  1870   std::vector<OurReader::StructuredError> allErrors;
  1871   for (Errors::const_iterator itError = errors_.begin();
  1872        itError != errors_.end();
  1874     const ErrorInfo& error = *itError;
  1875     OurReader::StructuredError structured;
  1876     structured.offset_start = error.token_.start_ - begin_;
  1877     structured.offset_limit = error.token_.end_ - begin_;
  1878     structured.message = error.message_;
  1879     allErrors.push_back(structured);
  1884 bool OurReader::pushError(
const Value& value, 
const JSONCPP_STRING& message) {
  1885   ptrdiff_t length = end_ - begin_;
  1886   if(value.getOffsetStart() > length
  1887     || value.getOffsetLimit() > length)
  1890   token.type_ = tokenError;
  1891   token.start_ = begin_ + value.getOffsetStart();
  1892   token.end_ = end_ + value.getOffsetLimit();
  1894   info.token_ = token;
  1895   info.message_ = message;
  1897   errors_.push_back(info);
  1901 bool OurReader::pushError(
const Value& value, 
const JSONCPP_STRING& message, 
const Value& extra) {
  1902   ptrdiff_t length = end_ - begin_;
  1903   if(value.getOffsetStart() > length
  1904     || value.getOffsetLimit() > length
  1905     || extra.getOffsetLimit() > length)
  1908   token.type_ = tokenError;
  1909   token.start_ = begin_ + value.getOffsetStart();
  1910   token.end_ = begin_ + value.getOffsetLimit();
  1912   info.token_ = token;
  1913   info.message_ = message;
  1914   info.extra_ = begin_ + extra.getOffsetStart();
  1915   errors_.push_back(info);
  1919 bool OurReader::good()
 const {
  1920   return !errors_.size();
  1924 class OurCharReader : 
public CharReader {
  1925   bool const collectComments_;
  1929     bool collectComments,
  1930     OurFeatures 
const& features)
  1931   : collectComments_(collectComments)
  1935       char const* beginDoc, 
char const* endDoc,
  1937     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
  1939       *errs = reader_.getFormattedErrorMessages();
  1954   OurFeatures features = OurFeatures::all();
  1957   features.allowDroppedNullPlaceholders_ = 
settings_[
"allowDroppedNullPlaceholders"].
asBool();
  1959   features.allowSingleQuotes_ = 
settings_[
"allowSingleQuotes"].
asBool();
  1963   features.allowSpecialFloats_ = 
settings_[
"allowSpecialFloats"].
asBool();
  1964   return new OurCharReader(collectComments, features);
  1968   valid_keys->clear();
  1969   valid_keys->insert(
"collectComments");
  1970   valid_keys->insert(
"allowComments");
  1971   valid_keys->insert(
"strictRoot");
  1972   valid_keys->insert(
"allowDroppedNullPlaceholders");
  1973   valid_keys->insert(
"allowNumericKeys");
  1974   valid_keys->insert(
"allowSingleQuotes");
  1975   valid_keys->insert(
"stackLimit");
  1976   valid_keys->insert(
"failIfExtra");
  1977   valid_keys->insert(
"rejectDupKeys");
  1978   valid_keys->insert(
"allowSpecialFloats");
  1983   if (!invalid) invalid = &my_invalid;  
  1985   std::set<JSONCPP_STRING> valid_keys;
  1988   size_t n = keys.size();
  1989   for (
size_t i = 0; i < n; ++i) {
  1991     if (valid_keys.find(key) == valid_keys.end()) {
  1995   return 0u == inv.
size();
  2005   (*settings)[
"allowComments"] = 
false;
  2006   (*settings)[
"strictRoot"] = 
true;
  2007   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
  2008   (*settings)[
"allowNumericKeys"] = 
false;
  2009   (*settings)[
"allowSingleQuotes"] = 
false;
  2010   (*settings)[
"stackLimit"] = 1000;
  2011   (*settings)[
"failIfExtra"] = 
true;
  2012   (*settings)[
"rejectDupKeys"] = 
true;
  2013   (*settings)[
"allowSpecialFloats"] = 
false;
  2020   (*settings)[
"collectComments"] = 
true;
  2021   (*settings)[
"allowComments"] = 
true;
  2022   (*settings)[
"strictRoot"] = 
false;
  2023   (*settings)[
"allowDroppedNullPlaceholders"] = 
false;
  2024   (*settings)[
"allowNumericKeys"] = 
false;
  2025   (*settings)[
"allowSingleQuotes"] = 
false;
  2026   (*settings)[
"stackLimit"] = 1000;
  2027   (*settings)[
"failIfExtra"] = 
false;
  2028   (*settings)[
"rejectDupKeys"] = 
false;
  2029   (*settings)[
"allowSpecialFloats"] = 
false;
  2041   ssin << sin.rdbuf();
  2043   char const* begin = doc.data();
  2044   char const* end = begin + doc.size();
  2047   return reader->parse(begin, end, root, errs);
  2055     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. 
Json::Value settings_
Configuration of this builder. 
Members getMemberNames() const
Return a list of the member names. 
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. 
bool parse(const std::string &document, Value &root, bool collectComments=true)
Read a Value from a JSON document. 
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. 
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)
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.