json test

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers json_reader.cpp Source File

json_reader.cpp

00001 // Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
00002 // Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
00003 // Distributed under MIT license, or public domain if desired and
00004 // recognized in your jurisdiction.
00005 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
00006 
00007 #if !defined(JSON_IS_AMALGAMATION)
00008 #include <json/assertions.h>
00009 #include <json/reader.h>
00010 #include <json/value.h>
00011 #include "json_tool.h"
00012 #endif // if !defined(JSON_IS_AMALGAMATION)
00013 #include <utility>
00014 #include <cstdio>
00015 #include <cassert>
00016 #include <cstring>
00017 #include <istream>
00018 #include <sstream>
00019 #include <memory>
00020 #include <set>
00021 #include <limits>
00022 
00023 #if defined(_MSC_VER)
00024 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
00025 #define snprintf sprintf_s
00026 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
00027 #define snprintf std::snprintf
00028 #else
00029 #define snprintf _snprintf
00030 #endif
00031 #elif defined(__ANDROID__) || defined(__QNXNTO__)
00032 #define snprintf snprintf
00033 #elif __cplusplus >= 201103L
00034 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
00035 #define snprintf std::snprintf
00036 #endif
00037 #endif
00038 
00039 #if defined(__QNXNTO__)
00040 #define sscanf std::sscanf
00041 #endif
00042 
00043 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
00044 // Disable warning about strdup being deprecated.
00045 #pragma warning(disable : 4996)
00046 #endif
00047 
00048 // Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
00049 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
00050 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000
00051 #endif
00052 
00053 using namespace std;
00054 
00055 static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
00056 
00057 namespace Json {
00058 
00059 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
00060 typedef std::unique_ptr<CharReader> CharReaderPtr;
00061 #else
00062 typedef std::auto_ptr<CharReader>   CharReaderPtr;
00063 #endif
00064 
00065 // Implementation of class Features
00066 // ////////////////////////////////
00067 
00068 Features::Features()
00069     : allowComments_(true), strictRoot_(false),
00070       allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
00071 
00072 Features Features::all() { return Features(); }
00073 
00074 Features Features::strictMode() {
00075   Features features;
00076   features.allowComments_ = false;
00077   features.strictRoot_ = true;
00078   features.allowDroppedNullPlaceholders_ = false;
00079   features.allowNumericKeys_ = false;
00080   return features;
00081 }
00082 
00083 // Implementation of class Reader
00084 // ////////////////////////////////
00085 
00086 bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
00087   for (; begin < end; ++begin)
00088     if (*begin == '\n' || *begin == '\r')
00089       return true;
00090   return false;
00091 }
00092 
00093 // Class Reader
00094 // //////////////////////////////////////////////////////////////////
00095 
00096 Reader::Reader()
00097     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
00098       lastValue_(), commentsBefore_(), features_(Features::all()),
00099       collectComments_() {}
00100 
00101 Reader::Reader(const Features& features)
00102     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
00103       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
00104 }
00105 
00106 bool
00107 Reader::parse(const std::string& document, Value& root, bool collectComments) {
00108   document_.assign(document.begin(), document.end());
00109   const char* begin = document_.c_str();
00110   const char* end = begin + document_.length();
00111   return parse(begin, end, root, collectComments);
00112 }
00113 
00114 bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
00115   // std::istream_iterator<char> begin(sin);
00116   // std::istream_iterator<char> end;
00117   // Those would allow streamed input from a file, if parse() were a
00118   // template function.
00119 
00120   // Since JSONCPP_STRING is reference-counted, this at least does not
00121   // create an extra copy.
00122   JSONCPP_STRING doc;
00123   std::getline(sin, doc, (char)EOF);
00124   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
00125 }
00126 
00127 bool Reader::parse(const char* beginDoc,
00128                    const char* endDoc,
00129                    Value& root,
00130                    bool collectComments) {
00131   if (!features_.allowComments_) {
00132     collectComments = false;
00133   }
00134 
00135   begin_ = beginDoc;
00136   end_ = endDoc;
00137   collectComments_ = collectComments;
00138   current_ = begin_;
00139   lastValueEnd_ = 0;
00140   lastValue_ = 0;
00141   commentsBefore_.clear();
00142   errors_.clear();
00143   while (!nodes_.empty())
00144     nodes_.pop();
00145   nodes_.push(&root);
00146 
00147   bool successful = readValue();
00148   Token token;
00149   skipCommentTokens(token);
00150   if (collectComments_ && !commentsBefore_.empty())
00151     root.setComment(commentsBefore_, commentAfter);
00152   if (features_.strictRoot_) {
00153     if (!root.isArray() && !root.isObject()) {
00154       // Set error location to start of doc, ideally should be first token found
00155       // in doc
00156       token.type_ = tokenError;
00157       token.start_ = beginDoc;
00158       token.end_ = endDoc;
00159       addError(
00160           "A valid JSON document must be either an array or an object value.",
00161           token);
00162       return false;
00163     }
00164   }
00165   return successful;
00166 }
00167 
00168 bool Reader::readValue() {
00169   // readValue() may call itself only if it calls readObject() or ReadArray().
00170   // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). 
00171   // parse() executes one nodes_.push(), so > instead of >=.
00172   if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
00173 
00174   Token token;
00175   skipCommentTokens(token);
00176   bool successful = true;
00177 
00178   if (collectComments_ && !commentsBefore_.empty()) {
00179     currentValue().setComment(commentsBefore_, commentBefore);
00180     commentsBefore_.clear();
00181   }
00182 
00183   switch (token.type_) {
00184   case tokenObjectBegin:
00185     successful = readObject(token);
00186     currentValue().setOffsetLimit(current_ - begin_);
00187     break;
00188   case tokenArrayBegin:
00189     successful = readArray(token);
00190     currentValue().setOffsetLimit(current_ - begin_);
00191     break;
00192   case tokenNumber:
00193     successful = decodeNumber(token);
00194     break;
00195   case tokenString:
00196     successful = decodeString(token);
00197     break;
00198   case tokenTrue:
00199     {
00200     Value v(true);
00201     currentValue().swapPayload(v);
00202     currentValue().setOffsetStart(token.start_ - begin_);
00203     currentValue().setOffsetLimit(token.end_ - begin_);
00204     }
00205     break;
00206   case tokenFalse:
00207     {
00208     Value v(false);
00209     currentValue().swapPayload(v);
00210     currentValue().setOffsetStart(token.start_ - begin_);
00211     currentValue().setOffsetLimit(token.end_ - begin_);
00212     }
00213     break;
00214   case tokenNull:
00215     {
00216     Value v;
00217     currentValue().swapPayload(v);
00218     currentValue().setOffsetStart(token.start_ - begin_);
00219     currentValue().setOffsetLimit(token.end_ - begin_);
00220     }
00221     break;
00222   case tokenArraySeparator:
00223   case tokenObjectEnd:
00224   case tokenArrayEnd:
00225     if (features_.allowDroppedNullPlaceholders_) {
00226       // "Un-read" the current token and mark the current value as a null
00227       // token.
00228       current_--;
00229       Value v;
00230       currentValue().swapPayload(v);
00231       currentValue().setOffsetStart(current_ - begin_ - 1);
00232       currentValue().setOffsetLimit(current_ - begin_);
00233       break;
00234     } // Else, fall through...
00235   default:
00236     currentValue().setOffsetStart(token.start_ - begin_);
00237     currentValue().setOffsetLimit(token.end_ - begin_);
00238     return addError("Syntax error: value, object or array expected.", token);
00239   }
00240 
00241   if (collectComments_) {
00242     lastValueEnd_ = current_;
00243     lastValue_ = &currentValue();
00244   }
00245 
00246   return successful;
00247 }
00248 
00249 void Reader::skipCommentTokens(Token& token) {
00250   if (features_.allowComments_) {
00251     do {
00252       readToken(token);
00253     } while (token.type_ == tokenComment);
00254   } else {
00255     readToken(token);
00256   }
00257 }
00258 
00259 bool Reader::readToken(Token& token) {
00260   skipSpaces();
00261   token.start_ = current_;
00262   Char c = getNextChar();
00263   bool ok = true;
00264   switch (c) {
00265   case '{':
00266     token.type_ = tokenObjectBegin;
00267     break;
00268   case '}':
00269     token.type_ = tokenObjectEnd;
00270     break;
00271   case '[':
00272     token.type_ = tokenArrayBegin;
00273     break;
00274   case ']':
00275     token.type_ = tokenArrayEnd;
00276     break;
00277   case '"':
00278     token.type_ = tokenString;
00279     ok = readString();
00280     break;
00281   case '/':
00282     token.type_ = tokenComment;
00283     ok = readComment();
00284     break;
00285   case '0':
00286   case '1':
00287   case '2':
00288   case '3':
00289   case '4':
00290   case '5':
00291   case '6':
00292   case '7':
00293   case '8':
00294   case '9':
00295   case '-':
00296     token.type_ = tokenNumber;
00297     readNumber();
00298     break;
00299   case 't':
00300     token.type_ = tokenTrue;
00301     ok = match("rue", 3);
00302     break;
00303   case 'f':
00304     token.type_ = tokenFalse;
00305     ok = match("alse", 4);
00306     break;
00307   case 'n':
00308     token.type_ = tokenNull;
00309     ok = match("ull", 3);
00310     break;
00311   case ',':
00312     token.type_ = tokenArraySeparator;
00313     break;
00314   case ':':
00315     token.type_ = tokenMemberSeparator;
00316     break;
00317   case 0:
00318     token.type_ = tokenEndOfStream;
00319     break;
00320   default:
00321     ok = false;
00322     break;
00323   }
00324   if (!ok)
00325     token.type_ = tokenError;
00326   token.end_ = current_;
00327   return true;
00328 }
00329 
00330 void Reader::skipSpaces() {
00331   while (current_ != end_) {
00332     Char c = *current_;
00333     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
00334       ++current_;
00335     else
00336       break;
00337   }
00338 }
00339 
00340 bool Reader::match(Location pattern, int patternLength) {
00341   if (end_ - current_ < patternLength)
00342     return false;
00343   int index = patternLength;
00344   while (index--)
00345     if (current_[index] != pattern[index])
00346       return false;
00347   current_ += patternLength;
00348   return true;
00349 }
00350 
00351 bool Reader::readComment() {
00352   Location commentBegin = current_ - 1;
00353   Char c = getNextChar();
00354   bool successful = false;
00355   if (c == '*')
00356     successful = readCStyleComment();
00357   else if (c == '/')
00358     successful = readCppStyleComment();
00359   if (!successful)
00360     return false;
00361 
00362   if (collectComments_) {
00363     CommentPlacement  placement = commentBefore;
00364     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
00365       if (c != '*' || !containsNewLine(commentBegin, current_))
00366         placement = commentAfterOnSameLine;
00367     }
00368 
00369     addComment(commentBegin, current_, placement);
00370   }
00371   return true;
00372 }
00373 
00374 JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
00375   JSONCPP_STRING normalized;
00376   normalized.reserve(static_cast<size_t>(end - begin));
00377   Reader::Location current = begin;
00378   while (current != end) {
00379     char c = *current++;
00380     if (c == '\r') {
00381       if (current != end && *current == '\n')
00382          // convert dos EOL
00383          ++current;
00384       // convert Mac EOL
00385       normalized += '\n';
00386     } else {
00387       normalized += c;
00388     }
00389   }
00390   return normalized;
00391 }
00392 
00393 void
00394 Reader::addComment(Location begin, Location end, CommentPlacement  placement) {
00395   assert(collectComments_);
00396   const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
00397   if (placement == commentAfterOnSameLine) {
00398     assert(lastValue_ != 0);
00399     lastValue_->setComment(normalized, placement);
00400   } else {
00401     commentsBefore_ += normalized;
00402   }
00403 }
00404 
00405 bool Reader::readCStyleComment() {
00406   while ((current_ + 1) < end_) {
00407     Char c = getNextChar();
00408     if (c == '*' && *current_ == '/')
00409       break;
00410   }
00411   return getNextChar() == '/';
00412 }
00413 
00414 bool Reader::readCppStyleComment() {
00415   while (current_ != end_) {
00416     Char c = getNextChar();
00417     if (c == '\n')
00418       break;
00419     if (c == '\r') {
00420       // Consume DOS EOL. It will be normalized in addComment.
00421       if (current_ != end_ && *current_ == '\n')
00422         getNextChar();
00423       // Break on Moc OS 9 EOL.
00424       break;
00425     }
00426   }
00427   return true;
00428 }
00429 
00430 void Reader::readNumber() {
00431   const char *p = current_;
00432   char c = '0'; // stopgap for already consumed character
00433   // integral part
00434   while (c >= '0' && c <= '9')
00435     c = (current_ = p) < end_ ? *p++ : '\0';
00436   // fractional part
00437   if (c == '.') {
00438     c = (current_ = p) < end_ ? *p++ : '\0';
00439     while (c >= '0' && c <= '9')
00440       c = (current_ = p) < end_ ? *p++ : '\0';
00441   }
00442   // exponential part
00443   if (c == 'e' || c == 'E') {
00444     c = (current_ = p) < end_ ? *p++ : '\0';
00445     if (c == '+' || c == '-')
00446       c = (current_ = p) < end_ ? *p++ : '\0';
00447     while (c >= '0' && c <= '9')
00448       c = (current_ = p) < end_ ? *p++ : '\0';
00449   }
00450 }
00451 
00452 bool Reader::readString() {
00453   Char c = '\0';
00454   while (current_ != end_) {
00455     c = getNextChar();
00456     if (c == '\\')
00457       getNextChar();
00458     else if (c == '"')
00459       break;
00460   }
00461   return c == '"';
00462 }
00463 
00464 bool Reader::readObject(Token& tokenStart) {
00465   Token tokenName;
00466   JSONCPP_STRING name;
00467   Value init(objectValue);
00468   currentValue().swapPayload(init);
00469   currentValue().setOffsetStart(tokenStart.start_ - begin_);
00470   while (readToken(tokenName)) {
00471     bool initialTokenOk = true;
00472     while (tokenName.type_ == tokenComment && initialTokenOk)
00473       initialTokenOk = readToken(tokenName);
00474     if (!initialTokenOk)
00475       break;
00476     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
00477       return true;
00478     name.clear();
00479     if (tokenName.type_ == tokenString) {
00480       if (!decodeString(tokenName, name))
00481         return recoverFromError(tokenObjectEnd);
00482     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
00483       Value numberName;
00484       if (!decodeNumber(tokenName, numberName))
00485         return recoverFromError(tokenObjectEnd);
00486       name = JSONCPP_STRING(numberName.asCString());
00487     } else {
00488       break;
00489     }
00490 
00491     Token colon;
00492     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
00493       return addErrorAndRecover(
00494           "Missing ':' after object member name", colon, tokenObjectEnd);
00495     }
00496     Value& value = currentValue()[name];
00497     nodes_.push(&value);
00498     bool ok = readValue();
00499     nodes_.pop();
00500     if (!ok) // error already set
00501       return recoverFromError(tokenObjectEnd);
00502 
00503     Token comma;
00504     if (!readToken(comma) ||
00505         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
00506          comma.type_ != tokenComment)) {
00507       return addErrorAndRecover(
00508           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
00509     }
00510     bool finalizeTokenOk = true;
00511     while (comma.type_ == tokenComment && finalizeTokenOk)
00512       finalizeTokenOk = readToken(comma);
00513     if (comma.type_ == tokenObjectEnd)
00514       return true;
00515   }
00516   return addErrorAndRecover(
00517       "Missing '}' or object member name", tokenName, tokenObjectEnd);
00518 }
00519 
00520 bool Reader::readArray(Token& tokenStart) {
00521   Value init(arrayValue);
00522   currentValue().swapPayload(init);
00523   currentValue().setOffsetStart(tokenStart.start_ - begin_);
00524   skipSpaces();
00525   if (current_ != end_ && *current_ == ']') // empty array
00526   {
00527     Token endArray;
00528     readToken(endArray);
00529     return true;
00530   }
00531   int index = 0;
00532   for (;;) {
00533     Value& value = currentValue()[index++];
00534     nodes_.push(&value);
00535     bool ok = readValue();
00536     nodes_.pop();
00537     if (!ok) // error already set
00538       return recoverFromError(tokenArrayEnd);
00539 
00540     Token token;
00541     // Accept Comment after last item in the array.
00542     ok = readToken(token);
00543     while (token.type_ == tokenComment && ok) {
00544       ok = readToken(token);
00545     }
00546     bool badTokenType =
00547         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
00548     if (!ok || badTokenType) {
00549       return addErrorAndRecover(
00550           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
00551     }
00552     if (token.type_ == tokenArrayEnd)
00553       break;
00554   }
00555   return true;
00556 }
00557 
00558 bool Reader::decodeNumber(Token& token) {
00559   Value decoded;
00560   if (!decodeNumber(token, decoded))
00561     return false;
00562   currentValue().swapPayload(decoded);
00563   currentValue().setOffsetStart(token.start_ - begin_);
00564   currentValue().setOffsetLimit(token.end_ - begin_);
00565   return true;
00566 }
00567 
00568 bool Reader::decodeNumber(Token& token, Value& decoded) {
00569   // Attempts to parse the number as an integer. If the number is
00570   // larger than the maximum supported value of an integer then
00571   // we decode the number as a double.
00572   Location current = token.start_;
00573   bool isNegative = *current == '-';
00574   if (isNegative)
00575     ++current;
00576   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
00577   Value::LargestUInt maxIntegerValue =
00578       isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
00579                  : Value::maxLargestUInt;
00580   Value::LargestUInt threshold = maxIntegerValue / 10;
00581   Value::LargestUInt value = 0;
00582   while (current < token.end_) {
00583     Char c = *current++;
00584     if (c < '0' || c > '9')
00585       return decodeDouble(token, decoded);
00586     Value::UInt digit(static_cast<Value::UInt>(c - '0'));
00587     if (value >= threshold) {
00588       // We've hit or exceeded the max value divided by 10 (rounded down). If
00589       // a) we've only just touched the limit, b) this is the last digit, and
00590       // c) it's small enough to fit in that rounding delta, we're okay.
00591       // Otherwise treat this number as a double to avoid overflow.
00592       if (value > threshold || current != token.end_ ||
00593           digit > maxIntegerValue % 10) {
00594         return decodeDouble(token, decoded);
00595       }
00596     }
00597     value = value * 10 + digit;
00598   }
00599   if (isNegative && value == maxIntegerValue)
00600     decoded = Value::minLargestInt;
00601   else if (isNegative)
00602     decoded = -Value::LargestInt(value);
00603   else if (value <= Value::LargestUInt(Value::maxInt))
00604     decoded = Value::LargestInt(value);
00605   else
00606     decoded = value;
00607   return true;
00608 }
00609 
00610 bool Reader::decodeDouble(Token& token) {
00611   Value decoded;
00612   if (!decodeDouble(token, decoded))
00613     return false;
00614   currentValue().swapPayload(decoded);
00615   currentValue().setOffsetStart(token.start_ - begin_);
00616   currentValue().setOffsetLimit(token.end_ - begin_);
00617   return true;
00618 }
00619 
00620 bool Reader::decodeDouble(Token& token, Value& decoded) {
00621   double value = 0;
00622   JSONCPP_STRING buffer(token.start_, token.end_);
00623   JSONCPP_ISTRINGSTREAM is(buffer);
00624   if (!(is >> value))
00625     return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
00626                         "' is not a number.",
00627                     token);
00628   decoded = value;
00629   return true;
00630 }
00631 
00632 bool Reader::decodeString(Token& token) {
00633   JSONCPP_STRING decoded_string;
00634   if (!decodeString(token, decoded_string))
00635     return false;
00636   Value decoded(decoded_string);
00637   currentValue().swapPayload(decoded);
00638   currentValue().setOffsetStart(token.start_ - begin_);
00639   currentValue().setOffsetLimit(token.end_ - begin_);
00640   return true;
00641 }
00642 
00643 bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
00644   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
00645   Location current = token.start_ + 1; // skip '"'
00646   Location end = token.end_ - 1;       // do not include '"'
00647   while (current != end) {
00648     Char c = *current++;
00649     if (c == '"')
00650       break;
00651     else if (c == '\\') {
00652       if (current == end)
00653         return addError("Empty escape sequence in string", token, current);
00654       Char escape = *current++;
00655       switch (escape) {
00656       case '"':
00657         decoded += '"';
00658         break;
00659       case '/':
00660         decoded += '/';
00661         break;
00662       case '\\':
00663         decoded += '\\';
00664         break;
00665       case 'b':
00666         decoded += '\b';
00667         break;
00668       case 'f':
00669         decoded += '\f';
00670         break;
00671       case 'n':
00672         decoded += '\n';
00673         break;
00674       case 'r':
00675         decoded += '\r';
00676         break;
00677       case 't':
00678         decoded += '\t';
00679         break;
00680       case 'u': {
00681         unsigned int unicode;
00682         if (!decodeUnicodeCodePoint(token, current, end, unicode))
00683           return false;
00684         decoded += codePointToUTF8(unicode);
00685       } break;
00686       default:
00687         return addError("Bad escape sequence in string", token, current);
00688       }
00689     } else {
00690       decoded += c;
00691     }
00692   }
00693   return true;
00694 }
00695 
00696 bool Reader::decodeUnicodeCodePoint(Token& token,
00697                                     Location& current,
00698                                     Location end,
00699                                     unsigned int& unicode) {
00700 
00701   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
00702     return false;
00703   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
00704     // surrogate pairs
00705     if (end - current < 6)
00706       return addError(
00707           "additional six characters expected to parse unicode surrogate pair.",
00708           token,
00709           current);
00710     unsigned int surrogatePair;
00711     if (*(current++) == '\\' && *(current++) == 'u') {
00712       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
00713         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
00714       } else
00715         return false;
00716     } else
00717       return addError("expecting another \\u token to begin the second half of "
00718                       "a unicode surrogate pair",
00719                       token,
00720                       current);
00721   }
00722   return true;
00723 }
00724 
00725 bool Reader::decodeUnicodeEscapeSequence(Token& token,
00726                                          Location& current,
00727                                          Location end,
00728                                          unsigned int& ret_unicode) {
00729   if (end - current < 4)
00730     return addError(
00731         "Bad unicode escape sequence in string: four digits expected.",
00732         token,
00733         current);
00734   int unicode = 0;
00735   for (int index = 0; index < 4; ++index) {
00736     Char c = *current++;
00737     unicode *= 16;
00738     if (c >= '0' && c <= '9')
00739       unicode += c - '0';
00740     else if (c >= 'a' && c <= 'f')
00741       unicode += c - 'a' + 10;
00742     else if (c >= 'A' && c <= 'F')
00743       unicode += c - 'A' + 10;
00744     else
00745       return addError(
00746           "Bad unicode escape sequence in string: hexadecimal digit expected.",
00747           token,
00748           current);
00749   }
00750   ret_unicode = static_cast<unsigned int>(unicode);
00751   return true;
00752 }
00753 
00754 bool
00755 Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
00756   ErrorInfo info;
00757   info.token_ = token;
00758   info.message_ = message;
00759   info.extra_ = extra;
00760   errors_.push_back(info);
00761   return false;
00762 }
00763 
00764 bool Reader::recoverFromError(TokenType skipUntilToken) {
00765   size_t const errorCount = errors_.size();
00766   Token skip;
00767   for (;;) {
00768     if (!readToken(skip))
00769       errors_.resize(errorCount); // discard errors caused by recovery
00770     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
00771       break;
00772   }
00773   errors_.resize(errorCount);
00774   return false;
00775 }
00776 
00777 bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
00778                                 Token& token,
00779                                 TokenType skipUntilToken) {
00780   addError(message, token);
00781   return recoverFromError(skipUntilToken);
00782 }
00783 
00784 Value& Reader::currentValue() { return *(nodes_.top()); }
00785 
00786 Reader::Char Reader::getNextChar() {
00787   if (current_ == end_)
00788     return 0;
00789   return *current_++;
00790 }
00791 
00792 void Reader::getLocationLineAndColumn(Location location,
00793                                       int& line,
00794                                       int& column) const {
00795   Location current = begin_;
00796   Location lastLineStart = current;
00797   line = 0;
00798   while (current < location && current != end_) {
00799     Char c = *current++;
00800     if (c == '\r') {
00801       if (*current == '\n')
00802         ++current;
00803       lastLineStart = current;
00804       ++line;
00805     } else if (c == '\n') {
00806       lastLineStart = current;
00807       ++line;
00808     }
00809   }
00810   // column & line start at 1
00811   column = int(location - lastLineStart) + 1;
00812   ++line;
00813 }
00814 
00815 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
00816   int line, column;
00817   getLocationLineAndColumn(location, line, column);
00818   char buffer[18 + 16 + 16 + 1];
00819   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
00820   return buffer;
00821 }
00822 
00823 // Deprecated. Preserved for backward compatibility
00824 JSONCPP_STRING Reader::getFormatedErrorMessages() const {
00825   return getFormattedErrorMessages();
00826 }
00827 
00828 JSONCPP_STRING Reader::getFormattedErrorMessages() const {
00829   JSONCPP_STRING formattedMessage;
00830   for (Errors::const_iterator itError = errors_.begin();
00831        itError != errors_.end();
00832        ++itError) {
00833     const ErrorInfo& error = *itError;
00834     formattedMessage +=
00835         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
00836     formattedMessage += "  " + error.message_ + "\n";
00837     if (error.extra_)
00838       formattedMessage +=
00839           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
00840   }
00841   return formattedMessage;
00842 }
00843 
00844 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
00845   std::vector<Reader::StructuredError> allErrors;
00846   for (Errors::const_iterator itError = errors_.begin();
00847        itError != errors_.end();
00848        ++itError) {
00849     const ErrorInfo& error = *itError;
00850     Reader::StructuredError structured;
00851     structured.offset_start = error.token_.start_ - begin_;
00852     structured.offset_limit = error.token_.end_ - begin_;
00853     structured.message = error.message_;
00854     allErrors.push_back(structured);
00855   }
00856   return allErrors;
00857 }
00858 
00859 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
00860   ptrdiff_t const length = end_ - begin_;
00861   if(value.getOffsetStart() > length
00862     || value.getOffsetLimit() > length)
00863     return false;
00864   Token token;
00865   token.type_ = tokenError;
00866   token.start_ = begin_ + value.getOffsetStart();
00867   token.end_ = end_ + value.getOffsetLimit();
00868   ErrorInfo info;
00869   info.token_ = token;
00870   info.message_ = message;
00871   info.extra_ = 0;
00872   errors_.push_back(info);
00873   return true;
00874 }
00875 
00876 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
00877   ptrdiff_t const length = end_ - begin_;
00878   if(value.getOffsetStart() > length
00879     || value.getOffsetLimit() > length
00880     || extra.getOffsetLimit() > length)
00881     return false;
00882   Token token;
00883   token.type_ = tokenError;
00884   token.start_ = begin_ + value.getOffsetStart();
00885   token.end_ = begin_ + value.getOffsetLimit();
00886   ErrorInfo info;
00887   info.token_ = token;
00888   info.message_ = message;
00889   info.extra_ = begin_ + extra.getOffsetStart();
00890   errors_.push_back(info);
00891   return true;
00892 }
00893 
00894 bool Reader::good() const {
00895   return !errors_.size();
00896 }
00897 
00898 // exact copy of Features
00899 class OurFeatures {
00900 public:
00901   static OurFeatures all();
00902   bool allowComments_;
00903   bool strictRoot_;
00904   bool allowDroppedNullPlaceholders_;
00905   bool allowNumericKeys_;
00906   bool allowSingleQuotes_;
00907   bool failIfExtra_;
00908   bool rejectDupKeys_;
00909   bool allowSpecialFloats_;
00910   int stackLimit_;
00911 };  // OurFeatures
00912 
00913 // exact copy of Implementation of class Features
00914 // ////////////////////////////////
00915 
00916 OurFeatures OurFeatures::all() { return OurFeatures(); }
00917 
00918 // Implementation of class Reader
00919 // ////////////////////////////////
00920 
00921 // exact copy of Reader, renamed to OurReader
00922 class OurReader {
00923 public:
00924   typedef char Char;
00925   typedef const Char* Location;
00926   struct StructuredError {
00927     ptrdiff_t offset_start;
00928     ptrdiff_t offset_limit;
00929     JSONCPP_STRING message;
00930   };
00931 
00932   OurReader(OurFeatures const& features);
00933   bool parse(const char* beginDoc,
00934              const char* endDoc,
00935              Value& root,
00936              bool collectComments = true);
00937   JSONCPP_STRING getFormattedErrorMessages() const;
00938   std::vector<StructuredError> getStructuredErrors() const;
00939   bool pushError(const Value& value, const JSONCPP_STRING& message);
00940   bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
00941   bool good() const;
00942 
00943 private:
00944   OurReader(OurReader const&);  // no impl
00945   void operator=(OurReader const&);  // no impl
00946 
00947   enum TokenType {
00948     tokenEndOfStream = 0,
00949     tokenObjectBegin,
00950     tokenObjectEnd,
00951     tokenArrayBegin,
00952     tokenArrayEnd,
00953     tokenString,
00954     tokenNumber,
00955     tokenTrue,
00956     tokenFalse,
00957     tokenNull,
00958     tokenNaN,
00959     tokenPosInf,
00960     tokenNegInf,
00961     tokenArraySeparator,
00962     tokenMemberSeparator,
00963     tokenComment,
00964     tokenError
00965   };
00966 
00967   class Token {
00968   public:
00969     TokenType type_;
00970     Location start_;
00971     Location end_;
00972   };
00973 
00974   class ErrorInfo {
00975   public:
00976     Token token_;
00977     JSONCPP_STRING message_;
00978     Location extra_;
00979   };
00980 
00981   typedef std::deque<ErrorInfo> Errors;
00982 
00983   bool readToken(Token& token);
00984   void skipSpaces();
00985   bool match(Location pattern, int patternLength);
00986   bool readComment();
00987   bool readCStyleComment();
00988   bool readCppStyleComment();
00989   bool readString();
00990   bool readStringSingleQuote();
00991   bool readNumber(bool checkInf);
00992   bool readValue();
00993   bool readObject(Token& token);
00994   bool readArray(Token& token);
00995   bool decodeNumber(Token& token);
00996   bool decodeNumber(Token& token, Value& decoded);
00997   bool decodeString(Token& token);
00998   bool decodeString(Token& token, JSONCPP_STRING& decoded);
00999   bool decodeDouble(Token& token);
01000   bool decodeDouble(Token& token, Value& decoded);
01001   bool decodeUnicodeCodePoint(Token& token,
01002                               Location& current,
01003                               Location end,
01004                               unsigned int& unicode);
01005   bool decodeUnicodeEscapeSequence(Token& token,
01006                                    Location& current,
01007                                    Location end,
01008                                    unsigned int& unicode);
01009   bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
01010   bool recoverFromError(TokenType skipUntilToken);
01011   bool addErrorAndRecover(const JSONCPP_STRING& message,
01012                           Token& token,
01013                           TokenType skipUntilToken);
01014   void skipUntilSpace();
01015   Value& currentValue();
01016   Char getNextChar();
01017   void
01018   getLocationLineAndColumn(Location location, int& line, int& column) const;
01019   JSONCPP_STRING getLocationLineAndColumn(Location location) const;
01020   void addComment(Location begin, Location end, CommentPlacement  placement);
01021   void skipCommentTokens(Token& token);
01022 
01023   static JSONCPP_STRING normalizeEOL(Location begin, Location end);
01024   static bool containsNewLine(Location begin, Location end);
01025 
01026   typedef std::stack<Value*> Nodes;
01027   Nodes nodes_;
01028   Errors errors_;
01029   JSONCPP_STRING document_;
01030   Location begin_;
01031   Location end_;
01032   Location current_;
01033   Location lastValueEnd_;
01034   Value* lastValue_;
01035   JSONCPP_STRING commentsBefore_;
01036 
01037   OurFeatures const features_;
01038   bool collectComments_;
01039 };  // OurReader
01040 
01041 // complete copy of Read impl, for OurReader
01042 
01043 bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
01044   for (; begin < end; ++begin)
01045     if (*begin == '\n' || *begin == '\r')
01046       return true;
01047   return false;
01048 }
01049 
01050 OurReader::OurReader(OurFeatures const& features)
01051     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
01052       lastValue_(), commentsBefore_(),
01053       features_(features), collectComments_() {
01054 }
01055 
01056 bool OurReader::parse(const char* beginDoc,
01057                    const char* endDoc,
01058                    Value& root,
01059                    bool collectComments) {
01060   if (!features_.allowComments_) {
01061     collectComments = false;
01062   }
01063 
01064   begin_ = beginDoc;
01065   end_ = endDoc;
01066   collectComments_ = collectComments;
01067   current_ = begin_;
01068   lastValueEnd_ = 0;
01069   lastValue_ = 0;
01070   commentsBefore_.clear();
01071   errors_.clear();
01072   while (!nodes_.empty())
01073     nodes_.pop();
01074   nodes_.push(&root);
01075 
01076   bool successful = readValue();
01077   Token token;
01078   skipCommentTokens(token);
01079   if (features_.failIfExtra_) {
01080     if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
01081       addError("Extra non-whitespace after JSON value.", token);
01082       return false;
01083     }
01084   }
01085   if (collectComments_ && !commentsBefore_.empty())
01086     root.setComment(commentsBefore_, commentAfter);
01087   if (features_.strictRoot_) {
01088     if (!root.isArray() && !root.isObject()) {
01089       // Set error location to start of doc, ideally should be first token found
01090       // in doc
01091       token.type_ = tokenError;
01092       token.start_ = beginDoc;
01093       token.end_ = endDoc;
01094       addError(
01095           "A valid JSON document must be either an array or an object value.",
01096           token);
01097       return false;
01098     }
01099   }
01100   return successful;
01101 }
01102 
01103 bool OurReader::readValue() {
01104   //  To preserve the old behaviour we cast size_t to int.
01105   if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
01106   Token token;
01107   skipCommentTokens(token);
01108   bool successful = true;
01109 
01110   if (collectComments_ && !commentsBefore_.empty()) {
01111     currentValue().setComment(commentsBefore_, commentBefore);
01112     commentsBefore_.clear();
01113   }
01114 
01115   switch (token.type_) {
01116   case tokenObjectBegin:
01117     successful = readObject(token);
01118     currentValue().setOffsetLimit(current_ - begin_);
01119     break;
01120   case tokenArrayBegin:
01121     successful = readArray(token);
01122     currentValue().setOffsetLimit(current_ - begin_);
01123     break;
01124   case tokenNumber:
01125     successful = decodeNumber(token);
01126     break;
01127   case tokenString:
01128     successful = decodeString(token);
01129     break;
01130   case tokenTrue:
01131     {
01132     Value v(true);
01133     currentValue().swapPayload(v);
01134     currentValue().setOffsetStart(token.start_ - begin_);
01135     currentValue().setOffsetLimit(token.end_ - begin_);
01136     }
01137     break;
01138   case tokenFalse:
01139     {
01140     Value v(false);
01141     currentValue().swapPayload(v);
01142     currentValue().setOffsetStart(token.start_ - begin_);
01143     currentValue().setOffsetLimit(token.end_ - begin_);
01144     }
01145     break;
01146   case tokenNull:
01147     {
01148     Value v;
01149     currentValue().swapPayload(v);
01150     currentValue().setOffsetStart(token.start_ - begin_);
01151     currentValue().setOffsetLimit(token.end_ - begin_);
01152     }
01153     break;
01154   case tokenNaN:
01155     {
01156     Value v(std::numeric_limits<double>::quiet_NaN());
01157     currentValue().swapPayload(v);
01158     currentValue().setOffsetStart(token.start_ - begin_);
01159     currentValue().setOffsetLimit(token.end_ - begin_);
01160     }
01161     break;
01162   case tokenPosInf:
01163     {
01164     Value v(std::numeric_limits<double>::infinity());
01165     currentValue().swapPayload(v);
01166     currentValue().setOffsetStart(token.start_ - begin_);
01167     currentValue().setOffsetLimit(token.end_ - begin_);
01168     }
01169     break;
01170   case tokenNegInf:
01171     {
01172     Value v(-std::numeric_limits<double>::infinity());
01173     currentValue().swapPayload(v);
01174     currentValue().setOffsetStart(token.start_ - begin_);
01175     currentValue().setOffsetLimit(token.end_ - begin_);
01176     }
01177     break;
01178   case tokenArraySeparator:
01179   case tokenObjectEnd:
01180   case tokenArrayEnd:
01181     if (features_.allowDroppedNullPlaceholders_) {
01182       // "Un-read" the current token and mark the current value as a null
01183       // token.
01184       current_--;
01185       Value v;
01186       currentValue().swapPayload(v);
01187       currentValue().setOffsetStart(current_ - begin_ - 1);
01188       currentValue().setOffsetLimit(current_ - begin_);
01189       break;
01190     } // else, fall through ...
01191   default:
01192     currentValue().setOffsetStart(token.start_ - begin_);
01193     currentValue().setOffsetLimit(token.end_ - begin_);
01194     return addError("Syntax error: value, object or array expected.", token);
01195   }
01196 
01197   if (collectComments_) {
01198     lastValueEnd_ = current_;
01199     lastValue_ = &currentValue();
01200   }
01201 
01202   return successful;
01203 }
01204 
01205 void OurReader::skipCommentTokens(Token& token) {
01206   if (features_.allowComments_) {
01207     do {
01208       readToken(token);
01209     } while (token.type_ == tokenComment);
01210   } else {
01211     readToken(token);
01212   }
01213 }
01214 
01215 bool OurReader::readToken(Token& token) {
01216   skipSpaces();
01217   token.start_ = current_;
01218   Char c = getNextChar();
01219   bool ok = true;
01220   switch (c) {
01221   case '{':
01222     token.type_ = tokenObjectBegin;
01223     break;
01224   case '}':
01225     token.type_ = tokenObjectEnd;
01226     break;
01227   case '[':
01228     token.type_ = tokenArrayBegin;
01229     break;
01230   case ']':
01231     token.type_ = tokenArrayEnd;
01232     break;
01233   case '"':
01234     token.type_ = tokenString;
01235     ok = readString();
01236     break;
01237   case '\'':
01238     if (features_.allowSingleQuotes_) {
01239     token.type_ = tokenString;
01240     ok = readStringSingleQuote();
01241     break;
01242     } // else fall through
01243   case '/':
01244     token.type_ = tokenComment;
01245     ok = readComment();
01246     break;
01247   case '0':
01248   case '1':
01249   case '2':
01250   case '3':
01251   case '4':
01252   case '5':
01253   case '6':
01254   case '7':
01255   case '8':
01256   case '9':
01257     token.type_ = tokenNumber;
01258     readNumber(false);
01259     break;
01260   case '-':
01261     if (readNumber(true)) {
01262       token.type_ = tokenNumber;
01263     } else {
01264       token.type_ = tokenNegInf;
01265       ok = features_.allowSpecialFloats_ && match("nfinity", 7);
01266     }
01267     break;
01268   case 't':
01269     token.type_ = tokenTrue;
01270     ok = match("rue", 3);
01271     break;
01272   case 'f':
01273     token.type_ = tokenFalse;
01274     ok = match("alse", 4);
01275     break;
01276   case 'n':
01277     token.type_ = tokenNull;
01278     ok = match("ull", 3);
01279     break;
01280   case 'N':
01281     if (features_.allowSpecialFloats_) {
01282       token.type_ = tokenNaN;
01283       ok = match("aN", 2);
01284     } else {
01285       ok = false;
01286     }
01287     break;
01288   case 'I':
01289     if (features_.allowSpecialFloats_) {
01290       token.type_ = tokenPosInf;
01291       ok = match("nfinity", 7);
01292     } else {
01293       ok = false;
01294     }
01295     break;
01296   case ',':
01297     token.type_ = tokenArraySeparator;
01298     break;
01299   case ':':
01300     token.type_ = tokenMemberSeparator;
01301     break;
01302   case 0:
01303     token.type_ = tokenEndOfStream;
01304     break;
01305   default:
01306     ok = false;
01307     break;
01308   }
01309   if (!ok)
01310     token.type_ = tokenError;
01311   token.end_ = current_;
01312   return true;
01313 }
01314 
01315 void OurReader::skipSpaces() {
01316   while (current_ != end_) {
01317     Char c = *current_;
01318     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
01319       ++current_;
01320     else
01321       break;
01322   }
01323 }
01324 
01325 bool OurReader::match(Location pattern, int patternLength) {
01326   if (end_ - current_ < patternLength)
01327     return false;
01328   int index = patternLength;
01329   while (index--)
01330     if (current_[index] != pattern[index])
01331       return false;
01332   current_ += patternLength;
01333   return true;
01334 }
01335 
01336 bool OurReader::readComment() {
01337   Location commentBegin = current_ - 1;
01338   Char c = getNextChar();
01339   bool successful = false;
01340   if (c == '*')
01341     successful = readCStyleComment();
01342   else if (c == '/')
01343     successful = readCppStyleComment();
01344   if (!successful)
01345     return false;
01346 
01347   if (collectComments_) {
01348     CommentPlacement  placement = commentBefore;
01349     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
01350       if (c != '*' || !containsNewLine(commentBegin, current_))
01351         placement = commentAfterOnSameLine;
01352     }
01353 
01354     addComment(commentBegin, current_, placement);
01355   }
01356   return true;
01357 }
01358 
01359 JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
01360   JSONCPP_STRING normalized;
01361   normalized.reserve(static_cast<size_t>(end - begin));
01362   OurReader::Location current = begin;
01363   while (current != end) {
01364     char c = *current++;
01365     if (c == '\r') {
01366       if (current != end && *current == '\n')
01367          // convert dos EOL
01368          ++current;
01369       // convert Mac EOL
01370       normalized += '\n';
01371     } else {
01372       normalized += c;
01373     }
01374   }
01375   return normalized;
01376 }
01377 
01378 void
01379 OurReader::addComment(Location begin, Location end, CommentPlacement  placement) {
01380   assert(collectComments_);
01381   const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
01382   if (placement == commentAfterOnSameLine) {
01383     assert(lastValue_ != 0);
01384     lastValue_->setComment(normalized, placement);
01385   } else {
01386     commentsBefore_ += normalized;
01387   }
01388 }
01389 
01390 bool OurReader::readCStyleComment() {
01391   while ((current_ + 1) < end_) {
01392     Char c = getNextChar();
01393     if (c == '*' && *current_ == '/')
01394       break;
01395   }
01396   return getNextChar() == '/';
01397 }
01398 
01399 bool OurReader::readCppStyleComment() {
01400   while (current_ != end_) {
01401     Char c = getNextChar();
01402     if (c == '\n')
01403       break;
01404     if (c == '\r') {
01405       // Consume DOS EOL. It will be normalized in addComment.
01406       if (current_ != end_ && *current_ == '\n')
01407         getNextChar();
01408       // Break on Moc OS 9 EOL.
01409       break;
01410     }
01411   }
01412   return true;
01413 }
01414 
01415 bool OurReader::readNumber(bool checkInf) {
01416   const char *p = current_;
01417   if (checkInf && p != end_ && *p == 'I') {
01418     current_ = ++p;
01419     return false;
01420   }
01421   char c = '0'; // stopgap for already consumed character
01422   // integral part
01423   while (c >= '0' && c <= '9')
01424     c = (current_ = p) < end_ ? *p++ : '\0';
01425   // fractional part
01426   if (c == '.') {
01427     c = (current_ = p) < end_ ? *p++ : '\0';
01428     while (c >= '0' && c <= '9')
01429       c = (current_ = p) < end_ ? *p++ : '\0';
01430   }
01431   // exponential part
01432   if (c == 'e' || c == 'E') {
01433     c = (current_ = p) < end_ ? *p++ : '\0';
01434     if (c == '+' || c == '-')
01435       c = (current_ = p) < end_ ? *p++ : '\0';
01436     while (c >= '0' && c <= '9')
01437       c = (current_ = p) < end_ ? *p++ : '\0';
01438   }
01439   return true;
01440 }
01441 bool OurReader::readString() {
01442   Char c = 0;
01443   while (current_ != end_) {
01444     c = getNextChar();
01445     if (c == '\\')
01446       getNextChar();
01447     else if (c == '"')
01448       break;
01449   }
01450   return c == '"';
01451 }
01452 
01453 
01454 bool OurReader::readStringSingleQuote() {
01455   Char c = 0;
01456   while (current_ != end_) {
01457     c = getNextChar();
01458     if (c == '\\')
01459       getNextChar();
01460     else if (c == '\'')
01461       break;
01462   }
01463   return c == '\'';
01464 }
01465 
01466 bool OurReader::readObject(Token& tokenStart) {
01467   Token tokenName;
01468   JSONCPP_STRING name;
01469   Value init(objectValue);
01470   currentValue().swapPayload(init);
01471   currentValue().setOffsetStart(tokenStart.start_ - begin_);
01472   while (readToken(tokenName)) {
01473     bool initialTokenOk = true;
01474     while (tokenName.type_ == tokenComment && initialTokenOk)
01475       initialTokenOk = readToken(tokenName);
01476     if (!initialTokenOk)
01477       break;
01478     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
01479       return true;
01480     name.clear();
01481     if (tokenName.type_ == tokenString) {
01482       if (!decodeString(tokenName, name))
01483         return recoverFromError(tokenObjectEnd);
01484     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
01485       Value numberName;
01486       if (!decodeNumber(tokenName, numberName))
01487         return recoverFromError(tokenObjectEnd);
01488       name = numberName.asString();
01489     } else {
01490       break;
01491     }
01492 
01493     Token colon;
01494     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
01495       return addErrorAndRecover(
01496           "Missing ':' after object member name", colon, tokenObjectEnd);
01497     }
01498     if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
01499     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
01500       JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
01501       return addErrorAndRecover(
01502           msg, tokenName, tokenObjectEnd);
01503     }
01504     Value& value = currentValue()[name];
01505     nodes_.push(&value);
01506     bool ok = readValue();
01507     nodes_.pop();
01508     if (!ok) // error already set
01509       return recoverFromError(tokenObjectEnd);
01510 
01511     Token comma;
01512     if (!readToken(comma) ||
01513         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
01514          comma.type_ != tokenComment)) {
01515       return addErrorAndRecover(
01516           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
01517     }
01518     bool finalizeTokenOk = true;
01519     while (comma.type_ == tokenComment && finalizeTokenOk)
01520       finalizeTokenOk = readToken(comma);
01521     if (comma.type_ == tokenObjectEnd)
01522       return true;
01523   }
01524   return addErrorAndRecover(
01525       "Missing '}' or object member name", tokenName, tokenObjectEnd);
01526 }
01527 
01528 bool OurReader::readArray(Token& tokenStart) {
01529   Value init(arrayValue);
01530   currentValue().swapPayload(init);
01531   currentValue().setOffsetStart(tokenStart.start_ - begin_);
01532   skipSpaces();
01533   if (current_ != end_ && *current_ == ']') // empty array
01534   {
01535     Token endArray;
01536     readToken(endArray);
01537     return true;
01538   }
01539   int index = 0;
01540   for (;;) {
01541     Value& value = currentValue()[index++];
01542     nodes_.push(&value);
01543     bool ok = readValue();
01544     nodes_.pop();
01545     if (!ok) // error already set
01546       return recoverFromError(tokenArrayEnd);
01547 
01548     Token token;
01549     // Accept Comment after last item in the array.
01550     ok = readToken(token);
01551     while (token.type_ == tokenComment && ok) {
01552       ok = readToken(token);
01553     }
01554     bool badTokenType =
01555         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
01556     if (!ok || badTokenType) {
01557       return addErrorAndRecover(
01558           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
01559     }
01560     if (token.type_ == tokenArrayEnd)
01561       break;
01562   }
01563   return true;
01564 }
01565 
01566 bool OurReader::decodeNumber(Token& token) {
01567   Value decoded;
01568   if (!decodeNumber(token, decoded))
01569     return false;
01570   currentValue().swapPayload(decoded);
01571   currentValue().setOffsetStart(token.start_ - begin_);
01572   currentValue().setOffsetLimit(token.end_ - begin_);
01573   return true;
01574 }
01575 
01576 bool OurReader::decodeNumber(Token& token, Value& decoded) {
01577   // Attempts to parse the number as an integer. If the number is
01578   // larger than the maximum supported value of an integer then
01579   // we decode the number as a double.
01580   Location current = token.start_;
01581   bool isNegative = *current == '-';
01582   if (isNegative)
01583     ++current;
01584   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
01585   Value::LargestUInt maxIntegerValue =
01586       isNegative ? Value::LargestUInt(-Value::minLargestInt)
01587                  : Value::maxLargestUInt;
01588   Value::LargestUInt threshold = maxIntegerValue / 10;
01589   Value::LargestUInt value = 0;
01590   while (current < token.end_) {
01591     Char c = *current++;
01592     if (c < '0' || c > '9')
01593       return decodeDouble(token, decoded);
01594     Value::UInt digit(static_cast<Value::UInt>(c - '0'));
01595     if (value >= threshold) {
01596       // We've hit or exceeded the max value divided by 10 (rounded down). If
01597       // a) we've only just touched the limit, b) this is the last digit, and
01598       // c) it's small enough to fit in that rounding delta, we're okay.
01599       // Otherwise treat this number as a double to avoid overflow.
01600       if (value > threshold || current != token.end_ ||
01601           digit > maxIntegerValue % 10) {
01602         return decodeDouble(token, decoded);
01603       }
01604     }
01605     value = value * 10 + digit;
01606   }
01607   if (isNegative)
01608     decoded = -Value::LargestInt(value);
01609   else if (value <= Value::LargestUInt(Value::maxInt))
01610     decoded = Value::LargestInt(value);
01611   else
01612     decoded = value;
01613   return true;
01614 }
01615 
01616 bool OurReader::decodeDouble(Token& token) {
01617   Value decoded;
01618   if (!decodeDouble(token, decoded))
01619     return false;
01620   currentValue().swapPayload(decoded);
01621   currentValue().setOffsetStart(token.start_ - begin_);
01622   currentValue().setOffsetLimit(token.end_ - begin_);
01623   return true;
01624 }
01625 
01626 bool OurReader::decodeDouble(Token& token, Value& decoded) {
01627   double value = 0;
01628   const int bufferSize = 32;
01629   int count;
01630   ptrdiff_t const length = token.end_ - token.start_;
01631 
01632   // Sanity check to avoid buffer overflow exploits.
01633   if (length < 0) {
01634     return addError("Unable to parse token length", token);
01635   }
01636   size_t const ulength = static_cast<size_t>(length);
01637 
01638   // Avoid using a string constant for the format control string given to
01639   // sscanf, as this can cause hard to debug crashes on OS X. See here for more
01640   // info:
01641   //
01642   //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
01643   char format[] = "%lf";
01644 
01645   if (length <= bufferSize) {
01646     Char buffer[bufferSize + 1];
01647     memcpy(buffer, token.start_, ulength);
01648     buffer[length] = 0;
01649     fixNumericLocaleInput(buffer, buffer + length);
01650     count = sscanf(buffer, format, &value);
01651   } else {
01652     JSONCPP_STRING buffer(token.start_, token.end_);
01653     count = sscanf(buffer.c_str(), format, &value);
01654   }
01655 
01656   if (count != 1)
01657     return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
01658                         "' is not a number.",
01659                     token);
01660   decoded = value;
01661   return true;
01662 }
01663 
01664 bool OurReader::decodeString(Token& token) {
01665   JSONCPP_STRING decoded_string;
01666   if (!decodeString(token, decoded_string))
01667     return false;
01668   Value decoded(decoded_string);
01669   currentValue().swapPayload(decoded);
01670   currentValue().setOffsetStart(token.start_ - begin_);
01671   currentValue().setOffsetLimit(token.end_ - begin_);
01672   return true;
01673 }
01674 
01675 bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
01676   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
01677   Location current = token.start_ + 1; // skip '"'
01678   Location end = token.end_ - 1;       // do not include '"'
01679   while (current != end) {
01680     Char c = *current++;
01681     if (c == '"')
01682       break;
01683     else if (c == '\\') {
01684       if (current == end)
01685         return addError("Empty escape sequence in string", token, current);
01686       Char escape = *current++;
01687       switch (escape) {
01688       case '"':
01689         decoded += '"';
01690         break;
01691       case '/':
01692         decoded += '/';
01693         break;
01694       case '\\':
01695         decoded += '\\';
01696         break;
01697       case 'b':
01698         decoded += '\b';
01699         break;
01700       case 'f':
01701         decoded += '\f';
01702         break;
01703       case 'n':
01704         decoded += '\n';
01705         break;
01706       case 'r':
01707         decoded += '\r';
01708         break;
01709       case 't':
01710         decoded += '\t';
01711         break;
01712       case 'u': {
01713         unsigned int unicode;
01714         if (!decodeUnicodeCodePoint(token, current, end, unicode))
01715           return false;
01716         decoded += codePointToUTF8(unicode);
01717       } break;
01718       default:
01719         return addError("Bad escape sequence in string", token, current);
01720       }
01721     } else {
01722       decoded += c;
01723     }
01724   }
01725   return true;
01726 }
01727 
01728 bool OurReader::decodeUnicodeCodePoint(Token& token,
01729                                     Location& current,
01730                                     Location end,
01731                                     unsigned int& unicode) {
01732 
01733   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
01734     return false;
01735   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
01736     // surrogate pairs
01737     if (end - current < 6)
01738       return addError(
01739           "additional six characters expected to parse unicode surrogate pair.",
01740           token,
01741           current);
01742     unsigned int surrogatePair;
01743     if (*(current++) == '\\' && *(current++) == 'u') {
01744       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
01745         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
01746       } else
01747         return false;
01748     } else
01749       return addError("expecting another \\u token to begin the second half of "
01750                       "a unicode surrogate pair",
01751                       token,
01752                       current);
01753   }
01754   return true;
01755 }
01756 
01757 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
01758                                          Location& current,
01759                                          Location end,
01760                                          unsigned int& ret_unicode) {
01761   if (end - current < 4)
01762     return addError(
01763         "Bad unicode escape sequence in string: four digits expected.",
01764         token,
01765         current);
01766   int unicode = 0;
01767   for (int index = 0; index < 4; ++index) {
01768     Char c = *current++;
01769     unicode *= 16;
01770     if (c >= '0' && c <= '9')
01771       unicode += c - '0';
01772     else if (c >= 'a' && c <= 'f')
01773       unicode += c - 'a' + 10;
01774     else if (c >= 'A' && c <= 'F')
01775       unicode += c - 'A' + 10;
01776     else
01777       return addError(
01778           "Bad unicode escape sequence in string: hexadecimal digit expected.",
01779           token,
01780           current);
01781   }
01782   ret_unicode = static_cast<unsigned int>(unicode);
01783   return true;
01784 }
01785 
01786 bool
01787 OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
01788   ErrorInfo info;
01789   info.token_ = token;
01790   info.message_ = message;
01791   info.extra_ = extra;
01792   errors_.push_back(info);
01793   return false;
01794 }
01795 
01796 bool OurReader::recoverFromError(TokenType skipUntilToken) {
01797   size_t errorCount = errors_.size();
01798   Token skip;
01799   for (;;) {
01800     if (!readToken(skip))
01801       errors_.resize(errorCount); // discard errors caused by recovery
01802     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
01803       break;
01804   }
01805   errors_.resize(errorCount);
01806   return false;
01807 }
01808 
01809 bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
01810                                 Token& token,
01811                                 TokenType skipUntilToken) {
01812   addError(message, token);
01813   return recoverFromError(skipUntilToken);
01814 }
01815 
01816 Value& OurReader::currentValue() { return *(nodes_.top()); }
01817 
01818 OurReader::Char OurReader::getNextChar() {
01819   if (current_ == end_)
01820     return 0;
01821   return *current_++;
01822 }
01823 
01824 void OurReader::getLocationLineAndColumn(Location location,
01825                                       int& line,
01826                                       int& column) const {
01827   Location current = begin_;
01828   Location lastLineStart = current;
01829   line = 0;
01830   while (current < location && current != end_) {
01831     Char c = *current++;
01832     if (c == '\r') {
01833       if (*current == '\n')
01834         ++current;
01835       lastLineStart = current;
01836       ++line;
01837     } else if (c == '\n') {
01838       lastLineStart = current;
01839       ++line;
01840     }
01841   }
01842   // column & line start at 1
01843   column = int(location - lastLineStart) + 1;
01844   ++line;
01845 }
01846 
01847 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
01848   int line, column;
01849   getLocationLineAndColumn(location, line, column);
01850   char buffer[18 + 16 + 16 + 1];
01851   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
01852   return buffer;
01853 }
01854 
01855 JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
01856   JSONCPP_STRING formattedMessage;
01857   for (Errors::const_iterator itError = errors_.begin();
01858        itError != errors_.end();
01859        ++itError) {
01860     const ErrorInfo& error = *itError;
01861     formattedMessage +=
01862         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
01863     formattedMessage += "  " + error.message_ + "\n";
01864     if (error.extra_)
01865       formattedMessage +=
01866           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
01867   }
01868   return formattedMessage;
01869 }
01870 
01871 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
01872   std::vector<OurReader::StructuredError> allErrors;
01873   for (Errors::const_iterator itError = errors_.begin();
01874        itError != errors_.end();
01875        ++itError) {
01876     const ErrorInfo& error = *itError;
01877     OurReader::StructuredError structured;
01878     structured.offset_start = error.token_.start_ - begin_;
01879     structured.offset_limit = error.token_.end_ - begin_;
01880     structured.message = error.message_;
01881     allErrors.push_back(structured);
01882   }
01883   return allErrors;
01884 }
01885 
01886 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
01887   ptrdiff_t length = end_ - begin_;
01888   if(value.getOffsetStart() > length
01889     || value.getOffsetLimit() > length)
01890     return false;
01891   Token token;
01892   token.type_ = tokenError;
01893   token.start_ = begin_ + value.getOffsetStart();
01894   token.end_ = end_ + value.getOffsetLimit();
01895   ErrorInfo info;
01896   info.token_ = token;
01897   info.message_ = message;
01898   info.extra_ = 0;
01899   errors_.push_back(info);
01900   return true;
01901 }
01902 
01903 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
01904   ptrdiff_t length = end_ - begin_;
01905   if(value.getOffsetStart() > length
01906     || value.getOffsetLimit() > length
01907     || extra.getOffsetLimit() > length)
01908     return false;
01909   Token token;
01910   token.type_ = tokenError;
01911   token.start_ = begin_ + value.getOffsetStart();
01912   token.end_ = begin_ + value.getOffsetLimit();
01913   ErrorInfo info;
01914   info.token_ = token;
01915   info.message_ = message;
01916   info.extra_ = begin_ + extra.getOffsetStart();
01917   errors_.push_back(info);
01918   return true;
01919 }
01920 
01921 bool OurReader::good() const {
01922   return !errors_.size();
01923 }
01924 
01925 
01926 class OurCharReader : public CharReader {
01927   bool const collectComments_;
01928   OurReader reader_;
01929 public:
01930   OurCharReader(
01931     bool collectComments,
01932     OurFeatures const& features)
01933   : collectComments_(collectComments)
01934   , reader_(features)
01935   {}
01936   bool parse(
01937       char const* beginDoc, char const* endDoc,
01938       Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
01939     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
01940     if (errs) {
01941       *errs = reader_.getFormattedErrorMessages();
01942     }
01943     return ok;
01944   }
01945 };
01946 
01947 CharReaderBuilder::CharReaderBuilder()
01948 {
01949   setDefaults(&settings_);
01950 }
01951 CharReaderBuilder::~CharReaderBuilder()
01952 {}
01953 CharReader* CharReaderBuilder::newCharReader() const
01954 {
01955   bool collectComments = settings_["collectComments"].asBool();
01956   OurFeatures features = OurFeatures::all();
01957   features.allowComments_ = settings_["allowComments"].asBool();
01958   features.strictRoot_ = settings_["strictRoot"].asBool();
01959   features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
01960   features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
01961   features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
01962   features.stackLimit_ = settings_["stackLimit"].asInt();
01963   features.failIfExtra_ = settings_["failIfExtra"].asBool();
01964   features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
01965   features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
01966   return new OurCharReader(collectComments, features);
01967 }
01968 static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
01969 {
01970   valid_keys->clear();
01971   valid_keys->insert("collectComments");
01972   valid_keys->insert("allowComments");
01973   valid_keys->insert("strictRoot");
01974   valid_keys->insert("allowDroppedNullPlaceholders");
01975   valid_keys->insert("allowNumericKeys");
01976   valid_keys->insert("allowSingleQuotes");
01977   valid_keys->insert("stackLimit");
01978   valid_keys->insert("failIfExtra");
01979   valid_keys->insert("rejectDupKeys");
01980   valid_keys->insert("allowSpecialFloats");
01981 }
01982 bool CharReaderBuilder::validate (Json::Value* invalid) const
01983 {
01984   Json::Value my_invalid;
01985   if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
01986   Json::Value& inv = *invalid;
01987   std::set<JSONCPP_STRING> valid_keys;
01988   getValidReaderKeys(&valid_keys);
01989   Value::Members keys = settings_.getMemberNames();
01990   size_t n = keys.size();
01991   for (size_t i = 0; i < n; ++i) {
01992     JSONCPP_STRING const& key = keys[i];
01993     if (valid_keys.find(key) == valid_keys.end()) {
01994       inv[key] = settings_[key];
01995     }
01996   }
01997   return 0u == inv.size();
01998 }
01999 Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
02000 {
02001   return settings_[key];
02002 }
02003 // static
02004 void CharReaderBuilder::strictMode(Json::Value* settings)
02005 {
02006 //! [CharReaderBuilderStrictMode]
02007   (*settings)["allowComments"] = false;
02008   (*settings)["strictRoot"] = true;
02009   (*settings)["allowDroppedNullPlaceholders"] = false;
02010   (*settings)["allowNumericKeys"] = false;
02011   (*settings)["allowSingleQuotes"] = false;
02012   (*settings)["stackLimit"] = 1000;
02013   (*settings)["failIfExtra"] = true;
02014   (*settings)["rejectDupKeys"] = true;
02015   (*settings)["allowSpecialFloats"] = false;
02016 //! [CharReaderBuilderStrictMode]
02017 }
02018 // static
02019 void CharReaderBuilder::setDefaults(Json::Value* settings)
02020 {
02021 //! [CharReaderBuilderDefaults]
02022   (*settings)["collectComments"] = true;
02023   (*settings)["allowComments"] = true;
02024   (*settings)["strictRoot"] = false;
02025   (*settings)["allowDroppedNullPlaceholders"] = false;
02026   (*settings)["allowNumericKeys"] = false;
02027   (*settings)["allowSingleQuotes"] = false;
02028   (*settings)["stackLimit"] = 1000;
02029   (*settings)["failIfExtra"] = false;
02030   (*settings)["rejectDupKeys"] = false;
02031   (*settings)["allowSpecialFloats"] = false;
02032 //! [CharReaderBuilderDefaults]
02033 }
02034 
02035 //////////////////////////////////
02036 // global functions
02037 
02038 bool parseFromStream(
02039     CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
02040     Value* root, JSONCPP_STRING* errs)
02041 {
02042   JSONCPP_OSTRINGSTREAM ssin;
02043   ssin << sin.rdbuf();
02044   JSONCPP_STRING doc = ssin.str();
02045   char const* begin = doc.data();
02046   char const* end = begin + doc.size();
02047   // Note that we do not actually need a null-terminator.
02048   CharReaderPtr const reader(fact.newCharReader());
02049   return reader->parse(begin, end, root, errs);
02050 }
02051 
02052 JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
02053   CharReaderBuilder b;
02054   JSONCPP_STRING errs;
02055   bool ok = parseFromStream(b, sin, &root, &errs);
02056   if (!ok) {
02057     throwRuntimeError(errs);
02058   }
02059   return sin;
02060 }
02061 
02062 } // namespace Json