Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:15:16

0001 /// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).
0002 /// It is intended to be used with #include "json/json.h"
0003 
0004 // //////////////////////////////////////////////////////////////////////
0005 // Beginning of content of file: LICENSE
0006 // //////////////////////////////////////////////////////////////////////
0007 
0008 /*
0009 The JsonCpp library's source code, including accompanying documentation, 
0010 tests and demonstration applications, are licensed under the following
0011 conditions...
0012 
0013 Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all 
0014 jurisdictions which recognize such a disclaimer. In such jurisdictions, 
0015 this software is released into the Public Domain.
0016 
0017 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
0018 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
0019 The JsonCpp Authors, and is released under the terms of the MIT License (see below).
0020 
0021 In jurisdictions which recognize Public Domain property, the user of this 
0022 software may choose to accept it either as 1) Public Domain, 2) under the 
0023 conditions of the MIT License (see below), or 3) under the terms of dual 
0024 Public Domain/MIT License conditions described here, as they choose.
0025 
0026 The MIT License is about as close to Public Domain as a license can get, and is
0027 described in clear, concise terms at:
0028 
0029    http://en.wikipedia.org/wiki/MIT_License
0030    
0031 The full text of the MIT License follows:
0032 
0033 ========================================================================
0034 Copyright (c) 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
0035 
0036 Permission is hereby granted, free of charge, to any person
0037 obtaining a copy of this software and associated documentation
0038 files (the "Software"), to deal in the Software without
0039 restriction, including without limitation the rights to use, copy,
0040 modify, merge, publish, distribute, sublicense, and/or sell copies
0041 of the Software, and to permit persons to whom the Software is
0042 furnished to do so, subject to the following conditions:
0043 
0044 The above copyright notice and this permission notice shall be
0045 included in all copies or substantial portions of the Software.
0046 
0047 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
0048 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
0049 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
0050 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
0051 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
0052 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0053 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
0054 SOFTWARE.
0055 ========================================================================
0056 (END LICENSE TEXT)
0057 
0058 The MIT license is compatible with both the GPL and commercial
0059 software, affording one all of the rights of Public Domain with the
0060 minor nuisance of being required to keep the above copyright notice
0061 and license text in the source code. Note also that by accepting the
0062 Public Domain "license" you can re-license your copy using whatever
0063 license you like.
0064 
0065 */
0066 
0067 // //////////////////////////////////////////////////////////////////////
0068 // End of content of file: LICENSE
0069 // //////////////////////////////////////////////////////////////////////
0070 
0071 
0072 
0073 
0074 
0075 
0076 #include "json/json.h"
0077 
0078 #ifndef JSON_IS_AMALGAMATION
0079 #error "Compile with -I PATH_TO_JSON_DIRECTORY"
0080 #endif
0081 
0082 
0083 // //////////////////////////////////////////////////////////////////////
0084 // Beginning of content of file: src/lib_json/json_tool.h
0085 // //////////////////////////////////////////////////////////////////////
0086 
0087 // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
0088 // Distributed under MIT license, or public domain if desired and
0089 // recognized in your jurisdiction.
0090 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
0091 
0092 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
0093 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
0094 
0095 
0096 // Also support old flag NO_LOCALE_SUPPORT
0097 #ifdef NO_LOCALE_SUPPORT
0098 #define JSONCPP_NO_LOCALE_SUPPORT
0099 #endif
0100 
0101 #ifndef JSONCPP_NO_LOCALE_SUPPORT
0102 #include <clocale>
0103 #endif
0104 
0105 /* This header provides common string manipulation support, such as UTF-8,
0106  * portable conversion from/to string...
0107  *
0108  * It is an internal header that must not be exposed.
0109  */
0110 
0111 namespace Json {
0112 static char getDecimalPoint() {
0113 #ifdef JSONCPP_NO_LOCALE_SUPPORT
0114   return '\0';
0115 #else
0116   struct lconv* lc = localeconv();
0117   return lc ? *(lc->decimal_point) : '\0';
0118 #endif
0119 }
0120 
0121 /// Converts a unicode code-point to UTF-8.
0122 static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
0123   JSONCPP_STRING result;
0124 
0125   // based on description from http://en.wikipedia.org/wiki/UTF-8
0126 
0127   if (cp <= 0x7f) {
0128     result.resize(1);
0129     result[0] = static_cast<char>(cp);
0130   } else if (cp <= 0x7FF) {
0131     result.resize(2);
0132     result[1] = static_cast<char>(0x80 | (0x3f & cp));
0133     result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
0134   } else if (cp <= 0xFFFF) {
0135     result.resize(3);
0136     result[2] = static_cast<char>(0x80 | (0x3f & cp));
0137     result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
0138     result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
0139   } else if (cp <= 0x10FFFF) {
0140     result.resize(4);
0141     result[3] = static_cast<char>(0x80 | (0x3f & cp));
0142     result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
0143     result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
0144     result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
0145   }
0146 
0147   return result;
0148 }
0149 
0150 enum {
0151   /// Constant that specify the size of the buffer that must be passed to
0152   /// uintToString.
0153   uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
0154 };
0155 
0156 // Defines a char buffer for use with uintToString().
0157 typedef char UIntToStringBuffer[uintToStringBufferSize];
0158 
0159 /** Converts an unsigned integer to string.
0160  * @param value Unsigned integer to convert to string
0161  * @param current Input/Output string buffer.
0162  *        Must have at least uintToStringBufferSize chars free.
0163  */
0164 static inline void uintToString(LargestUInt value, char*& current) {
0165   *--current = 0;
0166   do {
0167     *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
0168     value /= 10;
0169   } while (value != 0);
0170 }
0171 
0172 /** Change ',' to '.' everywhere in buffer.
0173  *
0174  * We had a sophisticated way, but it did not work in WinCE.
0175  * @see https://github.com/open-source-parsers/jsoncpp/pull/9
0176  */
0177 static inline void fixNumericLocale(char* begin, char* end) {
0178   while (begin < end) {
0179     if (*begin == ',') {
0180       *begin = '.';
0181     }
0182     ++begin;
0183   }
0184 }
0185 
0186 static inline void fixNumericLocaleInput(char* begin, char* end) {
0187   char decimalPoint = getDecimalPoint();
0188   if (decimalPoint != '\0' && decimalPoint != '.') {
0189     while (begin < end) {
0190       if (*begin == '.') {
0191         *begin = decimalPoint;
0192       }
0193       ++begin;
0194     }
0195   }
0196 }
0197 
0198 /**
0199  * Delete zeros in the end of string, if it isn't last zero before '.' character.
0200  */
0201 static inline void fixZerosInTheEnd(char* begin, char* end) {
0202   end--;
0203   while ((begin < end) && (*end == '0')) {
0204     // don't delete last zero before point.
0205     if (*(end - 1) != '.') {
0206       *end = '\0';
0207     }
0208     end--;
0209   }
0210 }
0211 
0212 } // namespace Json {
0213 
0214 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
0215 
0216 // //////////////////////////////////////////////////////////////////////
0217 // End of content of file: src/lib_json/json_tool.h
0218 // //////////////////////////////////////////////////////////////////////
0219 
0220 
0221 
0222 
0223 
0224 
0225 // //////////////////////////////////////////////////////////////////////
0226 // Beginning of content of file: src/lib_json/json_reader.cpp
0227 // //////////////////////////////////////////////////////////////////////
0228 
0229 // Copyright 2007-2011 Baptiste Lepilleur and The JsonCpp Authors
0230 // Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
0231 // Distributed under MIT license, or public domain if desired and
0232 // recognized in your jurisdiction.
0233 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
0234 
0235 #if !defined(JSON_IS_AMALGAMATION)
0236 #include <json/assertions.h>
0237 #include <json/reader.h>
0238 #include <json/value.h>
0239 #include "json_tool.h"
0240 #endif // if !defined(JSON_IS_AMALGAMATION)
0241 #include <utility>
0242 #include <cstdio>
0243 #include <cassert>
0244 #include <cstring>
0245 #include <istream>
0246 #include <sstream>
0247 #include <memory>
0248 #include <set>
0249 #include <limits>
0250 
0251 #if defined(_MSC_VER)
0252 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above 
0253 #define snprintf sprintf_s
0254 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
0255 #define snprintf std::snprintf
0256 #else
0257 #define snprintf _snprintf
0258 #endif
0259 #elif defined(__ANDROID__) || defined(__QNXNTO__)
0260 #define snprintf snprintf
0261 #elif __cplusplus >= 201103L
0262 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
0263 #define snprintf std::snprintf
0264 #endif
0265 #endif
0266 
0267 #if defined(__QNXNTO__)
0268 #define sscanf std::sscanf
0269 #endif
0270 
0271 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
0272 // Disable warning about strdup being deprecated.
0273 #pragma warning(disable : 4996)
0274 #endif
0275 
0276 // Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
0277 #if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
0278 #define JSONCPP_DEPRECATED_STACK_LIMIT 1000
0279 #endif
0280 
0281 static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
0282 
0283 namespace Json {
0284 
0285 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
0286 typedef std::unique_ptr<CharReader> CharReaderPtr;
0287 #else
0288 typedef std::auto_ptr<CharReader>   CharReaderPtr;
0289 #endif
0290 
0291 // Implementation of class Features
0292 // ////////////////////////////////
0293 
0294 Features::Features()
0295     : allowComments_(true), strictRoot_(false),
0296       allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
0297 
0298 Features Features::all() { return Features(); }
0299 
0300 Features Features::strictMode() {
0301   Features features;
0302   features.allowComments_ = false;
0303   features.strictRoot_ = true;
0304   features.allowDroppedNullPlaceholders_ = false;
0305   features.allowNumericKeys_ = false;
0306   return features;
0307 }
0308 
0309 // Implementation of class Reader
0310 // ////////////////////////////////
0311 
0312 bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
0313   for (; begin < end; ++begin)
0314     if (*begin == '\n' || *begin == '\r')
0315       return true;
0316   return false;
0317 }
0318 
0319 // Class Reader
0320 // //////////////////////////////////////////////////////////////////
0321 
0322 Reader::Reader()
0323     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
0324       lastValue_(), commentsBefore_(), features_(Features::all()),
0325       collectComments_() {}
0326 
0327 Reader::Reader(const Features& features)
0328     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
0329       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
0330 }
0331 
0332 bool
0333 Reader::parse(const std::string& document, Value& root, bool collectComments) {
0334   document_.assign(document.begin(), document.end());
0335   const char* begin = document_.c_str();
0336   const char* end = begin + document_.length();
0337   return parse(begin, end, root, collectComments);
0338 }
0339 
0340 bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
0341   // std::istream_iterator<char> begin(sin);
0342   // std::istream_iterator<char> end;
0343   // Those would allow streamed input from a file, if parse() were a
0344   // template function.
0345 
0346   // Since JSONCPP_STRING is reference-counted, this at least does not
0347   // create an extra copy.
0348   JSONCPP_STRING doc;
0349   std::getline(sin, doc, (char)EOF);
0350   return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
0351 }
0352 
0353 bool Reader::parse(const char* beginDoc,
0354                    const char* endDoc,
0355                    Value& root,
0356                    bool collectComments) {
0357   if (!features_.allowComments_) {
0358     collectComments = false;
0359   }
0360 
0361   begin_ = beginDoc;
0362   end_ = endDoc;
0363   collectComments_ = collectComments;
0364   current_ = begin_;
0365   lastValueEnd_ = 0;
0366   lastValue_ = 0;
0367   commentsBefore_.clear();
0368   errors_.clear();
0369   while (!nodes_.empty())
0370     nodes_.pop();
0371   nodes_.push(&root);
0372 
0373   bool successful = readValue();
0374   Token token;
0375   skipCommentTokens(token);
0376   if (collectComments_ && !commentsBefore_.empty())
0377     root.setComment(commentsBefore_, commentAfter);
0378   if (features_.strictRoot_) {
0379     if (!root.isArray() && !root.isObject()) {
0380       // Set error location to start of doc, ideally should be first token found
0381       // in doc
0382       token.type_ = tokenError;
0383       token.start_ = beginDoc;
0384       token.end_ = endDoc;
0385       addError(
0386           "A valid JSON document must be either an array or an object value.",
0387           token);
0388       return false;
0389     }
0390   }
0391   return successful;
0392 }
0393 
0394 bool Reader::readValue() {
0395   // readValue() may call itself only if it calls readObject() or ReadArray().
0396   // These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue(). 
0397   // parse() executes one nodes_.push(), so > instead of >=.
0398   if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
0399 
0400   Token token;
0401   skipCommentTokens(token);
0402   bool successful = true;
0403 
0404   if (collectComments_ && !commentsBefore_.empty()) {
0405     currentValue().setComment(commentsBefore_, commentBefore);
0406     commentsBefore_.clear();
0407   }
0408 
0409   switch (token.type_) {
0410   case tokenObjectBegin:
0411     successful = readObject(token);
0412     currentValue().setOffsetLimit(current_ - begin_);
0413     break;
0414   case tokenArrayBegin:
0415     successful = readArray(token);
0416     currentValue().setOffsetLimit(current_ - begin_);
0417     break;
0418   case tokenNumber:
0419     successful = decodeNumber(token);
0420     break;
0421   case tokenString:
0422     successful = decodeString(token);
0423     break;
0424   case tokenTrue:
0425     {
0426     Value v(true);
0427     currentValue().swapPayload(v);
0428     currentValue().setOffsetStart(token.start_ - begin_);
0429     currentValue().setOffsetLimit(token.end_ - begin_);
0430     }
0431     break;
0432   case tokenFalse:
0433     {
0434     Value v(false);
0435     currentValue().swapPayload(v);
0436     currentValue().setOffsetStart(token.start_ - begin_);
0437     currentValue().setOffsetLimit(token.end_ - begin_);
0438     }
0439     break;
0440   case tokenNull:
0441     {
0442     Value v;
0443     currentValue().swapPayload(v);
0444     currentValue().setOffsetStart(token.start_ - begin_);
0445     currentValue().setOffsetLimit(token.end_ - begin_);
0446     }
0447     break;
0448   case tokenArraySeparator:
0449   case tokenObjectEnd:
0450   case tokenArrayEnd:
0451     if (features_.allowDroppedNullPlaceholders_) {
0452       // "Un-read" the current token and mark the current value as a null
0453       // token.
0454       current_--;
0455       Value v;
0456       currentValue().swapPayload(v);
0457       currentValue().setOffsetStart(current_ - begin_ - 1);
0458       currentValue().setOffsetLimit(current_ - begin_);
0459       break;
0460     } // Else, fall through...
0461   default:
0462     currentValue().setOffsetStart(token.start_ - begin_);
0463     currentValue().setOffsetLimit(token.end_ - begin_);
0464     return addError("Syntax error: value, object or array expected.", token);
0465   }
0466 
0467   if (collectComments_) {
0468     lastValueEnd_ = current_;
0469     lastValue_ = &currentValue();
0470   }
0471 
0472   return successful;
0473 }
0474 
0475 void Reader::skipCommentTokens(Token& token) {
0476   if (features_.allowComments_) {
0477     do {
0478       readToken(token);
0479     } while (token.type_ == tokenComment);
0480   } else {
0481     readToken(token);
0482   }
0483 }
0484 
0485 bool Reader::readToken(Token& token) {
0486   skipSpaces();
0487   token.start_ = current_;
0488   Char c = getNextChar();
0489   bool ok = true;
0490   switch (c) {
0491   case '{':
0492     token.type_ = tokenObjectBegin;
0493     break;
0494   case '}':
0495     token.type_ = tokenObjectEnd;
0496     break;
0497   case '[':
0498     token.type_ = tokenArrayBegin;
0499     break;
0500   case ']':
0501     token.type_ = tokenArrayEnd;
0502     break;
0503   case '"':
0504     token.type_ = tokenString;
0505     ok = readString();
0506     break;
0507   case '/':
0508     token.type_ = tokenComment;
0509     ok = readComment();
0510     break;
0511   case '0':
0512   case '1':
0513   case '2':
0514   case '3':
0515   case '4':
0516   case '5':
0517   case '6':
0518   case '7':
0519   case '8':
0520   case '9':
0521   case '-':
0522     token.type_ = tokenNumber;
0523     readNumber();
0524     break;
0525   case 't':
0526     token.type_ = tokenTrue;
0527     ok = match("rue", 3);
0528     break;
0529   case 'f':
0530     token.type_ = tokenFalse;
0531     ok = match("alse", 4);
0532     break;
0533   case 'n':
0534     token.type_ = tokenNull;
0535     ok = match("ull", 3);
0536     break;
0537   case ',':
0538     token.type_ = tokenArraySeparator;
0539     break;
0540   case ':':
0541     token.type_ = tokenMemberSeparator;
0542     break;
0543   case 0:
0544     token.type_ = tokenEndOfStream;
0545     break;
0546   default:
0547     ok = false;
0548     break;
0549   }
0550   if (!ok)
0551     token.type_ = tokenError;
0552   token.end_ = current_;
0553   return true;
0554 }
0555 
0556 void Reader::skipSpaces() {
0557   while (current_ != end_) {
0558     Char c = *current_;
0559     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
0560       ++current_;
0561     else
0562       break;
0563   }
0564 }
0565 
0566 bool Reader::match(Location pattern, int patternLength) {
0567   if (end_ - current_ < patternLength)
0568     return false;
0569   int index = patternLength;
0570   while (index--)
0571     if (current_[index] != pattern[index])
0572       return false;
0573   current_ += patternLength;
0574   return true;
0575 }
0576 
0577 bool Reader::readComment() {
0578   Location commentBegin = current_ - 1;
0579   Char c = getNextChar();
0580   bool successful = false;
0581   if (c == '*')
0582     successful = readCStyleComment();
0583   else if (c == '/')
0584     successful = readCppStyleComment();
0585   if (!successful)
0586     return false;
0587 
0588   if (collectComments_) {
0589     CommentPlacement placement = commentBefore;
0590     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
0591       if (c != '*' || !containsNewLine(commentBegin, current_))
0592         placement = commentAfterOnSameLine;
0593     }
0594 
0595     addComment(commentBegin, current_, placement);
0596   }
0597   return true;
0598 }
0599 
0600 JSONCPP_STRING Reader::normalizeEOL(Reader::Location begin, Reader::Location end) {
0601   JSONCPP_STRING normalized;
0602   normalized.reserve(static_cast<size_t>(end - begin));
0603   Reader::Location current = begin;
0604   while (current != end) {
0605     char c = *current++;
0606     if (c == '\r') {
0607       if (current != end && *current == '\n')
0608          // convert dos EOL
0609          ++current;
0610       // convert Mac EOL
0611       normalized += '\n';
0612     } else {
0613       normalized += c;
0614     }
0615   }
0616   return normalized;
0617 }
0618 
0619 void
0620 Reader::addComment(Location begin, Location end, CommentPlacement placement) {
0621   assert(collectComments_);
0622   const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
0623   if (placement == commentAfterOnSameLine) {
0624     assert(lastValue_ != 0);
0625     lastValue_->setComment(normalized, placement);
0626   } else {
0627     commentsBefore_ += normalized;
0628   }
0629 }
0630 
0631 bool Reader::readCStyleComment() {
0632   while ((current_ + 1) < end_) {
0633     Char c = getNextChar();
0634     if (c == '*' && *current_ == '/')
0635       break;
0636   }
0637   return getNextChar() == '/';
0638 }
0639 
0640 bool Reader::readCppStyleComment() {
0641   while (current_ != end_) {
0642     Char c = getNextChar();
0643     if (c == '\n')
0644       break;
0645     if (c == '\r') {
0646       // Consume DOS EOL. It will be normalized in addComment.
0647       if (current_ != end_ && *current_ == '\n')
0648         getNextChar();
0649       // Break on Moc OS 9 EOL.
0650       break;
0651     }
0652   }
0653   return true;
0654 }
0655 
0656 void Reader::readNumber() {
0657   const char *p = current_;
0658   char c = '0'; // stopgap for already consumed character
0659   // integral part
0660   while (c >= '0' && c <= '9')
0661     c = (current_ = p) < end_ ? *p++ : '\0';
0662   // fractional part
0663   if (c == '.') {
0664     c = (current_ = p) < end_ ? *p++ : '\0';
0665     while (c >= '0' && c <= '9')
0666       c = (current_ = p) < end_ ? *p++ : '\0';
0667   }
0668   // exponential part
0669   if (c == 'e' || c == 'E') {
0670     c = (current_ = p) < end_ ? *p++ : '\0';
0671     if (c == '+' || c == '-')
0672       c = (current_ = p) < end_ ? *p++ : '\0';
0673     while (c >= '0' && c <= '9')
0674       c = (current_ = p) < end_ ? *p++ : '\0';
0675   }
0676 }
0677 
0678 bool Reader::readString() {
0679   Char c = '\0';
0680   while (current_ != end_) {
0681     c = getNextChar();
0682     if (c == '\\')
0683       getNextChar();
0684     else if (c == '"')
0685       break;
0686   }
0687   return c == '"';
0688 }
0689 
0690 bool Reader::readObject(Token& tokenStart) {
0691   Token tokenName;
0692   JSONCPP_STRING name;
0693   Value init(objectValue);
0694   currentValue().swapPayload(init);
0695   currentValue().setOffsetStart(tokenStart.start_ - begin_);
0696   while (readToken(tokenName)) {
0697     bool initialTokenOk = true;
0698     while (tokenName.type_ == tokenComment && initialTokenOk)
0699       initialTokenOk = readToken(tokenName);
0700     if (!initialTokenOk)
0701       break;
0702     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
0703       return true;
0704     name.clear();
0705     if (tokenName.type_ == tokenString) {
0706       if (!decodeString(tokenName, name))
0707         return recoverFromError(tokenObjectEnd);
0708     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
0709       Value numberName;
0710       if (!decodeNumber(tokenName, numberName))
0711         return recoverFromError(tokenObjectEnd);
0712       name = JSONCPP_STRING(numberName.asCString());
0713     } else {
0714       break;
0715     }
0716 
0717     Token colon;
0718     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
0719       return addErrorAndRecover(
0720           "Missing ':' after object member name", colon, tokenObjectEnd);
0721     }
0722     Value& value = currentValue()[name];
0723     nodes_.push(&value);
0724     bool ok = readValue();
0725     nodes_.pop();
0726     if (!ok) // error already set
0727       return recoverFromError(tokenObjectEnd);
0728 
0729     Token comma;
0730     if (!readToken(comma) ||
0731         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
0732          comma.type_ != tokenComment)) {
0733       return addErrorAndRecover(
0734           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
0735     }
0736     bool finalizeTokenOk = true;
0737     while (comma.type_ == tokenComment && finalizeTokenOk)
0738       finalizeTokenOk = readToken(comma);
0739     if (comma.type_ == tokenObjectEnd)
0740       return true;
0741   }
0742   return addErrorAndRecover(
0743       "Missing '}' or object member name", tokenName, tokenObjectEnd);
0744 }
0745 
0746 bool Reader::readArray(Token& tokenStart) {
0747   Value init(arrayValue);
0748   currentValue().swapPayload(init);
0749   currentValue().setOffsetStart(tokenStart.start_ - begin_);
0750   skipSpaces();
0751   if (current_ != end_ && *current_ == ']') // empty array
0752   {
0753     Token endArray;
0754     readToken(endArray);
0755     return true;
0756   }
0757   int index = 0;
0758   for (;;) {
0759     Value& value = currentValue()[index++];
0760     nodes_.push(&value);
0761     bool ok = readValue();
0762     nodes_.pop();
0763     if (!ok) // error already set
0764       return recoverFromError(tokenArrayEnd);
0765 
0766     Token token;
0767     // Accept Comment after last item in the array.
0768     ok = readToken(token);
0769     while (token.type_ == tokenComment && ok) {
0770       ok = readToken(token);
0771     }
0772     bool badTokenType =
0773         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
0774     if (!ok || badTokenType) {
0775       return addErrorAndRecover(
0776           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
0777     }
0778     if (token.type_ == tokenArrayEnd)
0779       break;
0780   }
0781   return true;
0782 }
0783 
0784 bool Reader::decodeNumber(Token& token) {
0785   Value decoded;
0786   if (!decodeNumber(token, decoded))
0787     return false;
0788   currentValue().swapPayload(decoded);
0789   currentValue().setOffsetStart(token.start_ - begin_);
0790   currentValue().setOffsetLimit(token.end_ - begin_);
0791   return true;
0792 }
0793 
0794 bool Reader::decodeNumber(Token& token, Value& decoded) {
0795   // Attempts to parse the number as an integer. If the number is
0796   // larger than the maximum supported value of an integer then
0797   // we decode the number as a double.
0798   Location current = token.start_;
0799   bool isNegative = *current == '-';
0800   if (isNegative)
0801     ++current;
0802   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
0803   Value::LargestUInt maxIntegerValue =
0804       isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
0805                  : Value::maxLargestUInt;
0806   Value::LargestUInt threshold = maxIntegerValue / 10;
0807   Value::LargestUInt value = 0;
0808   while (current < token.end_) {
0809     Char c = *current++;
0810     if (c < '0' || c > '9')
0811       return decodeDouble(token, decoded);
0812     Value::UInt digit(static_cast<Value::UInt>(c - '0'));
0813     if (value >= threshold) {
0814       // We've hit or exceeded the max value divided by 10 (rounded down). If
0815       // a) we've only just touched the limit, b) this is the last digit, and
0816       // c) it's small enough to fit in that rounding delta, we're okay.
0817       // Otherwise treat this number as a double to avoid overflow.
0818       if (value > threshold || current != token.end_ ||
0819           digit > maxIntegerValue % 10) {
0820         return decodeDouble(token, decoded);
0821       }
0822     }
0823     value = value * 10 + digit;
0824   }
0825   if (isNegative && value == maxIntegerValue)
0826     decoded = Value::minLargestInt;
0827   else if (isNegative)
0828     decoded = -Value::LargestInt(value);
0829   else if (value <= Value::LargestUInt(Value::maxInt))
0830     decoded = Value::LargestInt(value);
0831   else
0832     decoded = value;
0833   return true;
0834 }
0835 
0836 bool Reader::decodeDouble(Token& token) {
0837   Value decoded;
0838   if (!decodeDouble(token, decoded))
0839     return false;
0840   currentValue().swapPayload(decoded);
0841   currentValue().setOffsetStart(token.start_ - begin_);
0842   currentValue().setOffsetLimit(token.end_ - begin_);
0843   return true;
0844 }
0845 
0846 bool Reader::decodeDouble(Token& token, Value& decoded) {
0847   double value = 0;
0848   JSONCPP_STRING buffer(token.start_, token.end_);
0849   JSONCPP_ISTRINGSTREAM is(buffer);
0850   if (!(is >> value))
0851     return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
0852                         "' is not a number.",
0853                     token);
0854   decoded = value;
0855   return true;
0856 }
0857 
0858 bool Reader::decodeString(Token& token) {
0859   JSONCPP_STRING decoded_string;
0860   if (!decodeString(token, decoded_string))
0861     return false;
0862   Value decoded(decoded_string);
0863   currentValue().swapPayload(decoded);
0864   currentValue().setOffsetStart(token.start_ - begin_);
0865   currentValue().setOffsetLimit(token.end_ - begin_);
0866   return true;
0867 }
0868 
0869 bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
0870   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
0871   Location current = token.start_ + 1; // skip '"'
0872   Location end = token.end_ - 1;       // do not include '"'
0873   while (current != end) {
0874     Char c = *current++;
0875     if (c == '"')
0876       break;
0877     else if (c == '\\') {
0878       if (current == end)
0879         return addError("Empty escape sequence in string", token, current);
0880       Char escape = *current++;
0881       switch (escape) {
0882       case '"':
0883         decoded += '"';
0884         break;
0885       case '/':
0886         decoded += '/';
0887         break;
0888       case '\\':
0889         decoded += '\\';
0890         break;
0891       case 'b':
0892         decoded += '\b';
0893         break;
0894       case 'f':
0895         decoded += '\f';
0896         break;
0897       case 'n':
0898         decoded += '\n';
0899         break;
0900       case 'r':
0901         decoded += '\r';
0902         break;
0903       case 't':
0904         decoded += '\t';
0905         break;
0906       case 'u': {
0907         unsigned int unicode;
0908         if (!decodeUnicodeCodePoint(token, current, end, unicode))
0909           return false;
0910         decoded += codePointToUTF8(unicode);
0911       } break;
0912       default:
0913         return addError("Bad escape sequence in string", token, current);
0914       }
0915     } else {
0916       decoded += c;
0917     }
0918   }
0919   return true;
0920 }
0921 
0922 bool Reader::decodeUnicodeCodePoint(Token& token,
0923                                     Location& current,
0924                                     Location end,
0925                                     unsigned int& unicode) {
0926 
0927   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
0928     return false;
0929   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
0930     // surrogate pairs
0931     if (end - current < 6)
0932       return addError(
0933           "additional six characters expected to parse unicode surrogate pair.",
0934           token,
0935           current);
0936     unsigned int surrogatePair;
0937     if (*(current++) == '\\' && *(current++) == 'u') {
0938       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
0939         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
0940       } else
0941         return false;
0942     } else
0943       return addError("expecting another \\u token to begin the second half of "
0944                       "a unicode surrogate pair",
0945                       token,
0946                       current);
0947   }
0948   return true;
0949 }
0950 
0951 bool Reader::decodeUnicodeEscapeSequence(Token& token,
0952                                          Location& current,
0953                                          Location end,
0954                                          unsigned int& ret_unicode) {
0955   if (end - current < 4)
0956     return addError(
0957         "Bad unicode escape sequence in string: four digits expected.",
0958         token,
0959         current);
0960   int unicode = 0;
0961   for (int index = 0; index < 4; ++index) {
0962     Char c = *current++;
0963     unicode *= 16;
0964     if (c >= '0' && c <= '9')
0965       unicode += c - '0';
0966     else if (c >= 'a' && c <= 'f')
0967       unicode += c - 'a' + 10;
0968     else if (c >= 'A' && c <= 'F')
0969       unicode += c - 'A' + 10;
0970     else
0971       return addError(
0972           "Bad unicode escape sequence in string: hexadecimal digit expected.",
0973           token,
0974           current);
0975   }
0976   ret_unicode = static_cast<unsigned int>(unicode);
0977   return true;
0978 }
0979 
0980 bool
0981 Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
0982   ErrorInfo info;
0983   info.token_ = token;
0984   info.message_ = message;
0985   info.extra_ = extra;
0986   errors_.push_back(info);
0987   return false;
0988 }
0989 
0990 bool Reader::recoverFromError(TokenType skipUntilToken) {
0991   size_t const errorCount = errors_.size();
0992   Token skip;
0993   for (;;) {
0994     if (!readToken(skip))
0995       errors_.resize(errorCount); // discard errors caused by recovery
0996     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
0997       break;
0998   }
0999   errors_.resize(errorCount);
1000   return false;
1001 }
1002 
1003 bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
1004                                 Token& token,
1005                                 TokenType skipUntilToken) {
1006   addError(message, token);
1007   return recoverFromError(skipUntilToken);
1008 }
1009 
1010 Value& Reader::currentValue() { return *(nodes_.top()); }
1011 
1012 Reader::Char Reader::getNextChar() {
1013   if (current_ == end_)
1014     return 0;
1015   return *current_++;
1016 }
1017 
1018 void Reader::getLocationLineAndColumn(Location location,
1019                                       int& line,
1020                                       int& column) const {
1021   Location current = begin_;
1022   Location lastLineStart = current;
1023   line = 0;
1024   while (current < location && current != end_) {
1025     Char c = *current++;
1026     if (c == '\r') {
1027       if (*current == '\n')
1028         ++current;
1029       lastLineStart = current;
1030       ++line;
1031     } else if (c == '\n') {
1032       lastLineStart = current;
1033       ++line;
1034     }
1035   }
1036   // column & line start at 1
1037   column = int(location - lastLineStart) + 1;
1038   ++line;
1039 }
1040 
1041 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
1042   int line, column;
1043   getLocationLineAndColumn(location, line, column);
1044   char buffer[18 + 16 + 16 + 1];
1045   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
1046   return buffer;
1047 }
1048 
1049 // Deprecated. Preserved for backward compatibility
1050 JSONCPP_STRING Reader::getFormatedErrorMessages() const {
1051   return getFormattedErrorMessages();
1052 }
1053 
1054 JSONCPP_STRING Reader::getFormattedErrorMessages() const {
1055   JSONCPP_STRING formattedMessage;
1056   for (Errors::const_iterator itError = errors_.begin();
1057        itError != errors_.end();
1058        ++itError) {
1059     const ErrorInfo& error = *itError;
1060     formattedMessage +=
1061         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
1062     formattedMessage += "  " + error.message_ + "\n";
1063     if (error.extra_)
1064       formattedMessage +=
1065           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
1066   }
1067   return formattedMessage;
1068 }
1069 
1070 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
1071   std::vector<Reader::StructuredError> allErrors;
1072   for (Errors::const_iterator itError = errors_.begin();
1073        itError != errors_.end();
1074        ++itError) {
1075     const ErrorInfo& error = *itError;
1076     Reader::StructuredError structured;
1077     structured.offset_start = error.token_.start_ - begin_;
1078     structured.offset_limit = error.token_.end_ - begin_;
1079     structured.message = error.message_;
1080     allErrors.push_back(structured);
1081   }
1082   return allErrors;
1083 }
1084 
1085 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
1086   ptrdiff_t const length = end_ - begin_;
1087   if(value.getOffsetStart() > length
1088     || value.getOffsetLimit() > length)
1089     return false;
1090   Token token;
1091   token.type_ = tokenError;
1092   token.start_ = begin_ + value.getOffsetStart();
1093   token.end_ = end_ + value.getOffsetLimit();
1094   ErrorInfo info;
1095   info.token_ = token;
1096   info.message_ = message;
1097   info.extra_ = 0;
1098   errors_.push_back(info);
1099   return true;
1100 }
1101 
1102 bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
1103   ptrdiff_t const length = end_ - begin_;
1104   if(value.getOffsetStart() > length
1105     || value.getOffsetLimit() > length
1106     || extra.getOffsetLimit() > length)
1107     return false;
1108   Token token;
1109   token.type_ = tokenError;
1110   token.start_ = begin_ + value.getOffsetStart();
1111   token.end_ = begin_ + value.getOffsetLimit();
1112   ErrorInfo info;
1113   info.token_ = token;
1114   info.message_ = message;
1115   info.extra_ = begin_ + extra.getOffsetStart();
1116   errors_.push_back(info);
1117   return true;
1118 }
1119 
1120 bool Reader::good() const {
1121   return !errors_.size();
1122 }
1123 
1124 // exact copy of Features
1125 class OurFeatures {
1126 public:
1127   static OurFeatures all();
1128   bool allowComments_;
1129   bool strictRoot_;
1130   bool allowDroppedNullPlaceholders_;
1131   bool allowNumericKeys_;
1132   bool allowSingleQuotes_;
1133   bool failIfExtra_;
1134   bool rejectDupKeys_;
1135   bool allowSpecialFloats_;
1136   int stackLimit_;
1137 };  // OurFeatures
1138 
1139 // exact copy of Implementation of class Features
1140 // ////////////////////////////////
1141 
1142 OurFeatures OurFeatures::all() { return OurFeatures(); }
1143 
1144 // Implementation of class Reader
1145 // ////////////////////////////////
1146 
1147 // exact copy of Reader, renamed to OurReader
1148 class OurReader {
1149 public:
1150   typedef char Char;
1151   typedef const Char* Location;
1152   struct StructuredError {
1153     ptrdiff_t offset_start;
1154     ptrdiff_t offset_limit;
1155     JSONCPP_STRING message;
1156   };
1157 
1158   OurReader(OurFeatures const& features);
1159   bool parse(const char* beginDoc,
1160              const char* endDoc,
1161              Value& root,
1162              bool collectComments = true);
1163   JSONCPP_STRING getFormattedErrorMessages() const;
1164   std::vector<StructuredError> getStructuredErrors() const;
1165   bool pushError(const Value& value, const JSONCPP_STRING& message);
1166   bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
1167   bool good() const;
1168 
1169 private:
1170   OurReader(OurReader const&);  // no impl
1171   void operator=(OurReader const&);  // no impl
1172 
1173   enum TokenType {
1174     tokenEndOfStream = 0,
1175     tokenObjectBegin,
1176     tokenObjectEnd,
1177     tokenArrayBegin,
1178     tokenArrayEnd,
1179     tokenString,
1180     tokenNumber,
1181     tokenTrue,
1182     tokenFalse,
1183     tokenNull,
1184     tokenNaN,
1185     tokenPosInf,
1186     tokenNegInf,
1187     tokenArraySeparator,
1188     tokenMemberSeparator,
1189     tokenComment,
1190     tokenError
1191   };
1192 
1193   class Token {
1194   public:
1195     TokenType type_;
1196     Location start_;
1197     Location end_;
1198   };
1199 
1200   class ErrorInfo {
1201   public:
1202     Token token_;
1203     JSONCPP_STRING message_;
1204     Location extra_;
1205   };
1206 
1207   typedef std::deque<ErrorInfo> Errors;
1208 
1209   bool readToken(Token& token);
1210   void skipSpaces();
1211   bool match(Location pattern, int patternLength);
1212   bool readComment();
1213   bool readCStyleComment();
1214   bool readCppStyleComment();
1215   bool readString();
1216   bool readStringSingleQuote();
1217   bool readNumber(bool checkInf);
1218   bool readValue();
1219   bool readObject(Token& token);
1220   bool readArray(Token& token);
1221   bool decodeNumber(Token& token);
1222   bool decodeNumber(Token& token, Value& decoded);
1223   bool decodeString(Token& token);
1224   bool decodeString(Token& token, JSONCPP_STRING& decoded);
1225   bool decodeDouble(Token& token);
1226   bool decodeDouble(Token& token, Value& decoded);
1227   bool decodeUnicodeCodePoint(Token& token,
1228                               Location& current,
1229                               Location end,
1230                               unsigned int& unicode);
1231   bool decodeUnicodeEscapeSequence(Token& token,
1232                                    Location& current,
1233                                    Location end,
1234                                    unsigned int& unicode);
1235   bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
1236   bool recoverFromError(TokenType skipUntilToken);
1237   bool addErrorAndRecover(const JSONCPP_STRING& message,
1238                           Token& token,
1239                           TokenType skipUntilToken);
1240   void skipUntilSpace();
1241   Value& currentValue();
1242   Char getNextChar();
1243   void
1244   getLocationLineAndColumn(Location location, int& line, int& column) const;
1245   JSONCPP_STRING getLocationLineAndColumn(Location location) const;
1246   void addComment(Location begin, Location end, CommentPlacement placement);
1247   void skipCommentTokens(Token& token);
1248 
1249   static JSONCPP_STRING normalizeEOL(Location begin, Location end);
1250   static bool containsNewLine(Location begin, Location end);
1251 
1252   typedef std::stack<Value*> Nodes;
1253   Nodes nodes_;
1254   Errors errors_;
1255   JSONCPP_STRING document_;
1256   Location begin_;
1257   Location end_;
1258   Location current_;
1259   Location lastValueEnd_;
1260   Value* lastValue_;
1261   JSONCPP_STRING commentsBefore_;
1262 
1263   OurFeatures const features_;
1264   bool collectComments_;
1265 };  // OurReader
1266 
1267 // complete copy of Read impl, for OurReader
1268 
1269 bool OurReader::containsNewLine(OurReader::Location begin, OurReader::Location end) {
1270   for (; begin < end; ++begin)
1271     if (*begin == '\n' || *begin == '\r')
1272       return true;
1273   return false;
1274 }
1275 
1276 OurReader::OurReader(OurFeatures const& features)
1277     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1278       lastValue_(), commentsBefore_(),
1279       features_(features), collectComments_() {
1280 }
1281 
1282 bool OurReader::parse(const char* beginDoc,
1283                    const char* endDoc,
1284                    Value& root,
1285                    bool collectComments) {
1286   if (!features_.allowComments_) {
1287     collectComments = false;
1288   }
1289 
1290   begin_ = beginDoc;
1291   end_ = endDoc;
1292   collectComments_ = collectComments;
1293   current_ = begin_;
1294   lastValueEnd_ = 0;
1295   lastValue_ = 0;
1296   commentsBefore_.clear();
1297   errors_.clear();
1298   while (!nodes_.empty())
1299     nodes_.pop();
1300   nodes_.push(&root);
1301 
1302   bool successful = readValue();
1303   Token token;
1304   skipCommentTokens(token);
1305   if (features_.failIfExtra_) {
1306     if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
1307       addError("Extra non-whitespace after JSON value.", token);
1308       return false;
1309     }
1310   }
1311   if (collectComments_ && !commentsBefore_.empty())
1312     root.setComment(commentsBefore_, commentAfter);
1313   if (features_.strictRoot_) {
1314     if (!root.isArray() && !root.isObject()) {
1315       // Set error location to start of doc, ideally should be first token found
1316       // in doc
1317       token.type_ = tokenError;
1318       token.start_ = beginDoc;
1319       token.end_ = endDoc;
1320       addError(
1321           "A valid JSON document must be either an array or an object value.",
1322           token);
1323       return false;
1324     }
1325   }
1326   return successful;
1327 }
1328 
1329 bool OurReader::readValue() {
1330   //  To preserve the old behaviour we cast size_t to int.
1331   if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
1332   Token token;
1333   skipCommentTokens(token);
1334   bool successful = true;
1335 
1336   if (collectComments_ && !commentsBefore_.empty()) {
1337     currentValue().setComment(commentsBefore_, commentBefore);
1338     commentsBefore_.clear();
1339   }
1340 
1341   switch (token.type_) {
1342   case tokenObjectBegin:
1343     successful = readObject(token);
1344     currentValue().setOffsetLimit(current_ - begin_);
1345     break;
1346   case tokenArrayBegin:
1347     successful = readArray(token);
1348     currentValue().setOffsetLimit(current_ - begin_);
1349     break;
1350   case tokenNumber:
1351     successful = decodeNumber(token);
1352     break;
1353   case tokenString:
1354     successful = decodeString(token);
1355     break;
1356   case tokenTrue:
1357     {
1358     Value v(true);
1359     currentValue().swapPayload(v);
1360     currentValue().setOffsetStart(token.start_ - begin_);
1361     currentValue().setOffsetLimit(token.end_ - begin_);
1362     }
1363     break;
1364   case tokenFalse:
1365     {
1366     Value v(false);
1367     currentValue().swapPayload(v);
1368     currentValue().setOffsetStart(token.start_ - begin_);
1369     currentValue().setOffsetLimit(token.end_ - begin_);
1370     }
1371     break;
1372   case tokenNull:
1373     {
1374     Value v;
1375     currentValue().swapPayload(v);
1376     currentValue().setOffsetStart(token.start_ - begin_);
1377     currentValue().setOffsetLimit(token.end_ - begin_);
1378     }
1379     break;
1380   case tokenNaN:
1381     {
1382     Value v(std::numeric_limits<double>::quiet_NaN());
1383     currentValue().swapPayload(v);
1384     currentValue().setOffsetStart(token.start_ - begin_);
1385     currentValue().setOffsetLimit(token.end_ - begin_);
1386     }
1387     break;
1388   case tokenPosInf:
1389     {
1390     Value v(std::numeric_limits<double>::infinity());
1391     currentValue().swapPayload(v);
1392     currentValue().setOffsetStart(token.start_ - begin_);
1393     currentValue().setOffsetLimit(token.end_ - begin_);
1394     }
1395     break;
1396   case tokenNegInf:
1397     {
1398     Value v(-std::numeric_limits<double>::infinity());
1399     currentValue().swapPayload(v);
1400     currentValue().setOffsetStart(token.start_ - begin_);
1401     currentValue().setOffsetLimit(token.end_ - begin_);
1402     }
1403     break;
1404   case tokenArraySeparator:
1405   case tokenObjectEnd:
1406   case tokenArrayEnd:
1407     if (features_.allowDroppedNullPlaceholders_) {
1408       // "Un-read" the current token and mark the current value as a null
1409       // token.
1410       current_--;
1411       Value v;
1412       currentValue().swapPayload(v);
1413       currentValue().setOffsetStart(current_ - begin_ - 1);
1414       currentValue().setOffsetLimit(current_ - begin_);
1415       break;
1416     } // else, fall through ...
1417   default:
1418     currentValue().setOffsetStart(token.start_ - begin_);
1419     currentValue().setOffsetLimit(token.end_ - begin_);
1420     return addError("Syntax error: value, object or array expected.", token);
1421   }
1422 
1423   if (collectComments_) {
1424     lastValueEnd_ = current_;
1425     lastValue_ = &currentValue();
1426   }
1427 
1428   return successful;
1429 }
1430 
1431 void OurReader::skipCommentTokens(Token& token) {
1432   if (features_.allowComments_) {
1433     do {
1434       readToken(token);
1435     } while (token.type_ == tokenComment);
1436   } else {
1437     readToken(token);
1438   }
1439 }
1440 
1441 bool OurReader::readToken(Token& token) {
1442   skipSpaces();
1443   token.start_ = current_;
1444   Char c = getNextChar();
1445   bool ok = true;
1446   switch (c) {
1447   case '{':
1448     token.type_ = tokenObjectBegin;
1449     break;
1450   case '}':
1451     token.type_ = tokenObjectEnd;
1452     break;
1453   case '[':
1454     token.type_ = tokenArrayBegin;
1455     break;
1456   case ']':
1457     token.type_ = tokenArrayEnd;
1458     break;
1459   case '"':
1460     token.type_ = tokenString;
1461     ok = readString();
1462     break;
1463   case '\'':
1464     if (features_.allowSingleQuotes_) {
1465     token.type_ = tokenString;
1466     ok = readStringSingleQuote();
1467     break;
1468     } // else fall through
1469   case '/':
1470     token.type_ = tokenComment;
1471     ok = readComment();
1472     break;
1473   case '0':
1474   case '1':
1475   case '2':
1476   case '3':
1477   case '4':
1478   case '5':
1479   case '6':
1480   case '7':
1481   case '8':
1482   case '9':
1483     token.type_ = tokenNumber;
1484     readNumber(false);
1485     break;
1486   case '-':
1487     if (readNumber(true)) {
1488       token.type_ = tokenNumber;
1489     } else {
1490       token.type_ = tokenNegInf;
1491       ok = features_.allowSpecialFloats_ && match("nfinity", 7);
1492     }
1493     break;
1494   case 't':
1495     token.type_ = tokenTrue;
1496     ok = match("rue", 3);
1497     break;
1498   case 'f':
1499     token.type_ = tokenFalse;
1500     ok = match("alse", 4);
1501     break;
1502   case 'n':
1503     token.type_ = tokenNull;
1504     ok = match("ull", 3);
1505     break;
1506   case 'N':
1507     if (features_.allowSpecialFloats_) {
1508       token.type_ = tokenNaN;
1509       ok = match("aN", 2);
1510     } else {
1511       ok = false;
1512     }
1513     break;
1514   case 'I':
1515     if (features_.allowSpecialFloats_) {
1516       token.type_ = tokenPosInf;
1517       ok = match("nfinity", 7);
1518     } else {
1519       ok = false;
1520     }
1521     break;
1522   case ',':
1523     token.type_ = tokenArraySeparator;
1524     break;
1525   case ':':
1526     token.type_ = tokenMemberSeparator;
1527     break;
1528   case 0:
1529     token.type_ = tokenEndOfStream;
1530     break;
1531   default:
1532     ok = false;
1533     break;
1534   }
1535   if (!ok)
1536     token.type_ = tokenError;
1537   token.end_ = current_;
1538   return true;
1539 }
1540 
1541 void OurReader::skipSpaces() {
1542   while (current_ != end_) {
1543     Char c = *current_;
1544     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
1545       ++current_;
1546     else
1547       break;
1548   }
1549 }
1550 
1551 bool OurReader::match(Location pattern, int patternLength) {
1552   if (end_ - current_ < patternLength)
1553     return false;
1554   int index = patternLength;
1555   while (index--)
1556     if (current_[index] != pattern[index])
1557       return false;
1558   current_ += patternLength;
1559   return true;
1560 }
1561 
1562 bool OurReader::readComment() {
1563   Location commentBegin = current_ - 1;
1564   Char c = getNextChar();
1565   bool successful = false;
1566   if (c == '*')
1567     successful = readCStyleComment();
1568   else if (c == '/')
1569     successful = readCppStyleComment();
1570   if (!successful)
1571     return false;
1572 
1573   if (collectComments_) {
1574     CommentPlacement placement = commentBefore;
1575     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
1576       if (c != '*' || !containsNewLine(commentBegin, current_))
1577         placement = commentAfterOnSameLine;
1578     }
1579 
1580     addComment(commentBegin, current_, placement);
1581   }
1582   return true;
1583 }
1584 
1585 JSONCPP_STRING OurReader::normalizeEOL(OurReader::Location begin, OurReader::Location end) {
1586   JSONCPP_STRING normalized;
1587   normalized.reserve(static_cast<size_t>(end - begin));
1588   OurReader::Location current = begin;
1589   while (current != end) {
1590     char c = *current++;
1591     if (c == '\r') {
1592       if (current != end && *current == '\n')
1593          // convert dos EOL
1594          ++current;
1595       // convert Mac EOL
1596       normalized += '\n';
1597     } else {
1598       normalized += c;
1599     }
1600   }
1601   return normalized;
1602 }
1603 
1604 void
1605 OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
1606   assert(collectComments_);
1607   const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
1608   if (placement == commentAfterOnSameLine) {
1609     assert(lastValue_ != 0);
1610     lastValue_->setComment(normalized, placement);
1611   } else {
1612     commentsBefore_ += normalized;
1613   }
1614 }
1615 
1616 bool OurReader::readCStyleComment() {
1617   while ((current_ + 1) < end_) {
1618     Char c = getNextChar();
1619     if (c == '*' && *current_ == '/')
1620       break;
1621   }
1622   return getNextChar() == '/';
1623 }
1624 
1625 bool OurReader::readCppStyleComment() {
1626   while (current_ != end_) {
1627     Char c = getNextChar();
1628     if (c == '\n')
1629       break;
1630     if (c == '\r') {
1631       // Consume DOS EOL. It will be normalized in addComment.
1632       if (current_ != end_ && *current_ == '\n')
1633         getNextChar();
1634       // Break on Moc OS 9 EOL.
1635       break;
1636     }
1637   }
1638   return true;
1639 }
1640 
1641 bool OurReader::readNumber(bool checkInf) {
1642   const char *p = current_;
1643   if (checkInf && p != end_ && *p == 'I') {
1644     current_ = ++p;
1645     return false;
1646   }
1647   char c = '0'; // stopgap for already consumed character
1648   // integral part
1649   while (c >= '0' && c <= '9')
1650     c = (current_ = p) < end_ ? *p++ : '\0';
1651   // fractional part
1652   if (c == '.') {
1653     c = (current_ = p) < end_ ? *p++ : '\0';
1654     while (c >= '0' && c <= '9')
1655       c = (current_ = p) < end_ ? *p++ : '\0';
1656   }
1657   // exponential part
1658   if (c == 'e' || c == 'E') {
1659     c = (current_ = p) < end_ ? *p++ : '\0';
1660     if (c == '+' || c == '-')
1661       c = (current_ = p) < end_ ? *p++ : '\0';
1662     while (c >= '0' && c <= '9')
1663       c = (current_ = p) < end_ ? *p++ : '\0';
1664   }
1665   return true;
1666 }
1667 bool OurReader::readString() {
1668   Char c = 0;
1669   while (current_ != end_) {
1670     c = getNextChar();
1671     if (c == '\\')
1672       getNextChar();
1673     else if (c == '"')
1674       break;
1675   }
1676   return c == '"';
1677 }
1678 
1679 
1680 bool OurReader::readStringSingleQuote() {
1681   Char c = 0;
1682   while (current_ != end_) {
1683     c = getNextChar();
1684     if (c == '\\')
1685       getNextChar();
1686     else if (c == '\'')
1687       break;
1688   }
1689   return c == '\'';
1690 }
1691 
1692 bool OurReader::readObject(Token& tokenStart) {
1693   Token tokenName;
1694   JSONCPP_STRING name;
1695   Value init(objectValue);
1696   currentValue().swapPayload(init);
1697   currentValue().setOffsetStart(tokenStart.start_ - begin_);
1698   while (readToken(tokenName)) {
1699     bool initialTokenOk = true;
1700     while (tokenName.type_ == tokenComment && initialTokenOk)
1701       initialTokenOk = readToken(tokenName);
1702     if (!initialTokenOk)
1703       break;
1704     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
1705       return true;
1706     name.clear();
1707     if (tokenName.type_ == tokenString) {
1708       if (!decodeString(tokenName, name))
1709         return recoverFromError(tokenObjectEnd);
1710     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
1711       Value numberName;
1712       if (!decodeNumber(tokenName, numberName))
1713         return recoverFromError(tokenObjectEnd);
1714       name = numberName.asString();
1715     } else {
1716       break;
1717     }
1718 
1719     Token colon;
1720     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
1721       return addErrorAndRecover(
1722           "Missing ':' after object member name", colon, tokenObjectEnd);
1723     }
1724     if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
1725     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
1726       JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
1727       return addErrorAndRecover(
1728           msg, tokenName, tokenObjectEnd);
1729     }
1730     Value& value = currentValue()[name];
1731     nodes_.push(&value);
1732     bool ok = readValue();
1733     nodes_.pop();
1734     if (!ok) // error already set
1735       return recoverFromError(tokenObjectEnd);
1736 
1737     Token comma;
1738     if (!readToken(comma) ||
1739         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1740          comma.type_ != tokenComment)) {
1741       return addErrorAndRecover(
1742           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1743     }
1744     bool finalizeTokenOk = true;
1745     while (comma.type_ == tokenComment && finalizeTokenOk)
1746       finalizeTokenOk = readToken(comma);
1747     if (comma.type_ == tokenObjectEnd)
1748       return true;
1749   }
1750   return addErrorAndRecover(
1751       "Missing '}' or object member name", tokenName, tokenObjectEnd);
1752 }
1753 
1754 bool OurReader::readArray(Token& tokenStart) {
1755   Value init(arrayValue);
1756   currentValue().swapPayload(init);
1757   currentValue().setOffsetStart(tokenStart.start_ - begin_);
1758   skipSpaces();
1759   if (current_ != end_ && *current_ == ']') // empty array
1760   {
1761     Token endArray;
1762     readToken(endArray);
1763     return true;
1764   }
1765   int index = 0;
1766   for (;;) {
1767     Value& value = currentValue()[index++];
1768     nodes_.push(&value);
1769     bool ok = readValue();
1770     nodes_.pop();
1771     if (!ok) // error already set
1772       return recoverFromError(tokenArrayEnd);
1773 
1774     Token token;
1775     // Accept Comment after last item in the array.
1776     ok = readToken(token);
1777     while (token.type_ == tokenComment && ok) {
1778       ok = readToken(token);
1779     }
1780     bool badTokenType =
1781         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1782     if (!ok || badTokenType) {
1783       return addErrorAndRecover(
1784           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1785     }
1786     if (token.type_ == tokenArrayEnd)
1787       break;
1788   }
1789   return true;
1790 }
1791 
1792 bool OurReader::decodeNumber(Token& token) {
1793   Value decoded;
1794   if (!decodeNumber(token, decoded))
1795     return false;
1796   currentValue().swapPayload(decoded);
1797   currentValue().setOffsetStart(token.start_ - begin_);
1798   currentValue().setOffsetLimit(token.end_ - begin_);
1799   return true;
1800 }
1801 
1802 bool OurReader::decodeNumber(Token& token, Value& decoded) {
1803   // Attempts to parse the number as an integer. If the number is
1804   // larger than the maximum supported value of an integer then
1805   // we decode the number as a double.
1806   Location current = token.start_;
1807   bool isNegative = *current == '-';
1808   if (isNegative)
1809     ++current;
1810   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
1811   Value::LargestUInt maxIntegerValue =
1812       isNegative ? Value::LargestUInt(-Value::minLargestInt)
1813                  : Value::maxLargestUInt;
1814   Value::LargestUInt threshold = maxIntegerValue / 10;
1815   Value::LargestUInt value = 0;
1816   while (current < token.end_) {
1817     Char c = *current++;
1818     if (c < '0' || c > '9')
1819       return decodeDouble(token, decoded);
1820     Value::UInt digit(static_cast<Value::UInt>(c - '0'));
1821     if (value >= threshold) {
1822       // We've hit or exceeded the max value divided by 10 (rounded down). If
1823       // a) we've only just touched the limit, b) this is the last digit, and
1824       // c) it's small enough to fit in that rounding delta, we're okay.
1825       // Otherwise treat this number as a double to avoid overflow.
1826       if (value > threshold || current != token.end_ ||
1827           digit > maxIntegerValue % 10) {
1828         return decodeDouble(token, decoded);
1829       }
1830     }
1831     value = value * 10 + digit;
1832   }
1833   if (isNegative)
1834     decoded = -Value::LargestInt(value);
1835   else if (value <= Value::LargestUInt(Value::maxInt))
1836     decoded = Value::LargestInt(value);
1837   else
1838     decoded = value;
1839   return true;
1840 }
1841 
1842 bool OurReader::decodeDouble(Token& token) {
1843   Value decoded;
1844   if (!decodeDouble(token, decoded))
1845     return false;
1846   currentValue().swapPayload(decoded);
1847   currentValue().setOffsetStart(token.start_ - begin_);
1848   currentValue().setOffsetLimit(token.end_ - begin_);
1849   return true;
1850 }
1851 
1852 bool OurReader::decodeDouble(Token& token, Value& decoded) {
1853   double value = 0;
1854   const int bufferSize = 32;
1855   int count;
1856   ptrdiff_t const length = token.end_ - token.start_;
1857 
1858   // Sanity check to avoid buffer overflow exploits.
1859   if (length < 0) {
1860     return addError("Unable to parse token length", token);
1861   }
1862   size_t const ulength = static_cast<size_t>(length);
1863 
1864   // Avoid using a string constant for the format control string given to
1865   // sscanf, as this can cause hard to debug crashes on OS X. See here for more
1866   // info:
1867   //
1868   //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
1869   char format[] = "%lf";
1870 
1871   if (length <= bufferSize) {
1872     Char buffer[bufferSize + 1];
1873     memcpy(buffer, token.start_, ulength);
1874     buffer[length] = 0;
1875     fixNumericLocaleInput(buffer, buffer + length);
1876     count = sscanf(buffer, format, &value);
1877   } else {
1878     JSONCPP_STRING buffer(token.start_, token.end_);
1879     count = sscanf(buffer.c_str(), format, &value);
1880   }
1881 
1882   if (count != 1)
1883     return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
1884                         "' is not a number.",
1885                     token);
1886   decoded = value;
1887   return true;
1888 }
1889 
1890 bool OurReader::decodeString(Token& token) {
1891   JSONCPP_STRING decoded_string;
1892   if (!decodeString(token, decoded_string))
1893     return false;
1894   Value decoded(decoded_string);
1895   currentValue().swapPayload(decoded);
1896   currentValue().setOffsetStart(token.start_ - begin_);
1897   currentValue().setOffsetLimit(token.end_ - begin_);
1898   return true;
1899 }
1900 
1901 bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
1902   decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
1903   Location current = token.start_ + 1; // skip '"'
1904   Location end = token.end_ - 1;       // do not include '"'
1905   while (current != end) {
1906     Char c = *current++;
1907     if (c == '"')
1908       break;
1909     else if (c == '\\') {
1910       if (current == end)
1911         return addError("Empty escape sequence in string", token, current);
1912       Char escape = *current++;
1913       switch (escape) {
1914       case '"':
1915         decoded += '"';
1916         break;
1917       case '/':
1918         decoded += '/';
1919         break;
1920       case '\\':
1921         decoded += '\\';
1922         break;
1923       case 'b':
1924         decoded += '\b';
1925         break;
1926       case 'f':
1927         decoded += '\f';
1928         break;
1929       case 'n':
1930         decoded += '\n';
1931         break;
1932       case 'r':
1933         decoded += '\r';
1934         break;
1935       case 't':
1936         decoded += '\t';
1937         break;
1938       case 'u': {
1939         unsigned int unicode;
1940         if (!decodeUnicodeCodePoint(token, current, end, unicode))
1941           return false;
1942         decoded += codePointToUTF8(unicode);
1943       } break;
1944       default:
1945         return addError("Bad escape sequence in string", token, current);
1946       }
1947     } else {
1948       decoded += c;
1949     }
1950   }
1951   return true;
1952 }
1953 
1954 bool OurReader::decodeUnicodeCodePoint(Token& token,
1955                                     Location& current,
1956                                     Location end,
1957                                     unsigned int& unicode) {
1958 
1959   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
1960     return false;
1961   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
1962     // surrogate pairs
1963     if (end - current < 6)
1964       return addError(
1965           "additional six characters expected to parse unicode surrogate pair.",
1966           token,
1967           current);
1968     unsigned int surrogatePair;
1969     if (*(current++) == '\\' && *(current++) == 'u') {
1970       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
1971         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1972       } else
1973         return false;
1974     } else
1975       return addError("expecting another \\u token to begin the second half of "
1976                       "a unicode surrogate pair",
1977                       token,
1978                       current);
1979   }
1980   return true;
1981 }
1982 
1983 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
1984                                          Location& current,
1985                                          Location end,
1986                                          unsigned int& ret_unicode) {
1987   if (end - current < 4)
1988     return addError(
1989         "Bad unicode escape sequence in string: four digits expected.",
1990         token,
1991         current);
1992   int unicode = 0;
1993   for (int index = 0; index < 4; ++index) {
1994     Char c = *current++;
1995     unicode *= 16;
1996     if (c >= '0' && c <= '9')
1997       unicode += c - '0';
1998     else if (c >= 'a' && c <= 'f')
1999       unicode += c - 'a' + 10;
2000     else if (c >= 'A' && c <= 'F')
2001       unicode += c - 'A' + 10;
2002     else
2003       return addError(
2004           "Bad unicode escape sequence in string: hexadecimal digit expected.",
2005           token,
2006           current);
2007   }
2008   ret_unicode = static_cast<unsigned int>(unicode);
2009   return true;
2010 }
2011 
2012 bool
2013 OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
2014   ErrorInfo info;
2015   info.token_ = token;
2016   info.message_ = message;
2017   info.extra_ = extra;
2018   errors_.push_back(info);
2019   return false;
2020 }
2021 
2022 bool OurReader::recoverFromError(TokenType skipUntilToken) {
2023   size_t errorCount = errors_.size();
2024   Token skip;
2025   for (;;) {
2026     if (!readToken(skip))
2027       errors_.resize(errorCount); // discard errors caused by recovery
2028     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
2029       break;
2030   }
2031   errors_.resize(errorCount);
2032   return false;
2033 }
2034 
2035 bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
2036                                 Token& token,
2037                                 TokenType skipUntilToken) {
2038   addError(message, token);
2039   return recoverFromError(skipUntilToken);
2040 }
2041 
2042 Value& OurReader::currentValue() { return *(nodes_.top()); }
2043 
2044 OurReader::Char OurReader::getNextChar() {
2045   if (current_ == end_)
2046     return 0;
2047   return *current_++;
2048 }
2049 
2050 void OurReader::getLocationLineAndColumn(Location location,
2051                                       int& line,
2052                                       int& column) const {
2053   Location current = begin_;
2054   Location lastLineStart = current;
2055   line = 0;
2056   while (current < location && current != end_) {
2057     Char c = *current++;
2058     if (c == '\r') {
2059       if (*current == '\n')
2060         ++current;
2061       lastLineStart = current;
2062       ++line;
2063     } else if (c == '\n') {
2064       lastLineStart = current;
2065       ++line;
2066     }
2067   }
2068   // column & line start at 1
2069   column = int(location - lastLineStart) + 1;
2070   ++line;
2071 }
2072 
2073 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
2074   int line, column;
2075   getLocationLineAndColumn(location, line, column);
2076   char buffer[18 + 16 + 16 + 1];
2077   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
2078   return buffer;
2079 }
2080 
2081 JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
2082   JSONCPP_STRING formattedMessage;
2083   for (Errors::const_iterator itError = errors_.begin();
2084        itError != errors_.end();
2085        ++itError) {
2086     const ErrorInfo& error = *itError;
2087     formattedMessage +=
2088         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
2089     formattedMessage += "  " + error.message_ + "\n";
2090     if (error.extra_)
2091       formattedMessage +=
2092           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
2093   }
2094   return formattedMessage;
2095 }
2096 
2097 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
2098   std::vector<OurReader::StructuredError> allErrors;
2099   for (Errors::const_iterator itError = errors_.begin();
2100        itError != errors_.end();
2101        ++itError) {
2102     const ErrorInfo& error = *itError;
2103     OurReader::StructuredError structured;
2104     structured.offset_start = error.token_.start_ - begin_;
2105     structured.offset_limit = error.token_.end_ - begin_;
2106     structured.message = error.message_;
2107     allErrors.push_back(structured);
2108   }
2109   return allErrors;
2110 }
2111 
2112 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
2113   ptrdiff_t length = end_ - begin_;
2114   if(value.getOffsetStart() > length
2115     || value.getOffsetLimit() > length)
2116     return false;
2117   Token token;
2118   token.type_ = tokenError;
2119   token.start_ = begin_ + value.getOffsetStart();
2120   token.end_ = end_ + value.getOffsetLimit();
2121   ErrorInfo info;
2122   info.token_ = token;
2123   info.message_ = message;
2124   info.extra_ = 0;
2125   errors_.push_back(info);
2126   return true;
2127 }
2128 
2129 bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
2130   ptrdiff_t length = end_ - begin_;
2131   if(value.getOffsetStart() > length
2132     || value.getOffsetLimit() > length
2133     || extra.getOffsetLimit() > length)
2134     return false;
2135   Token token;
2136   token.type_ = tokenError;
2137   token.start_ = begin_ + value.getOffsetStart();
2138   token.end_ = begin_ + value.getOffsetLimit();
2139   ErrorInfo info;
2140   info.token_ = token;
2141   info.message_ = message;
2142   info.extra_ = begin_ + extra.getOffsetStart();
2143   errors_.push_back(info);
2144   return true;
2145 }
2146 
2147 bool OurReader::good() const {
2148   return !errors_.size();
2149 }
2150 
2151 
2152 class OurCharReader : public CharReader {
2153   bool const collectComments_;
2154   OurReader reader_;
2155 public:
2156   OurCharReader(
2157     bool collectComments,
2158     OurFeatures const& features)
2159   : collectComments_(collectComments)
2160   , reader_(features)
2161   {}
2162   bool parse(
2163       char const* beginDoc, char const* endDoc,
2164       Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
2165     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
2166     if (errs) {
2167       *errs = reader_.getFormattedErrorMessages();
2168     }
2169     return ok;
2170   }
2171 };
2172 
2173 CharReaderBuilder::CharReaderBuilder()
2174 {
2175   setDefaults(&settings_);
2176 }
2177 CharReaderBuilder::~CharReaderBuilder()
2178 {}
2179 CharReader* CharReaderBuilder::newCharReader() const
2180 {
2181   bool collectComments = settings_["collectComments"].asBool();
2182   OurFeatures features = OurFeatures::all();
2183   features.allowComments_ = settings_["allowComments"].asBool();
2184   features.strictRoot_ = settings_["strictRoot"].asBool();
2185   features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
2186   features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
2187   features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
2188   features.stackLimit_ = settings_["stackLimit"].asInt();
2189   features.failIfExtra_ = settings_["failIfExtra"].asBool();
2190   features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
2191   features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
2192   return new OurCharReader(collectComments, features);
2193 }
2194 static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
2195 {
2196   valid_keys->clear();
2197   valid_keys->insert("collectComments");
2198   valid_keys->insert("allowComments");
2199   valid_keys->insert("strictRoot");
2200   valid_keys->insert("allowDroppedNullPlaceholders");
2201   valid_keys->insert("allowNumericKeys");
2202   valid_keys->insert("allowSingleQuotes");
2203   valid_keys->insert("stackLimit");
2204   valid_keys->insert("failIfExtra");
2205   valid_keys->insert("rejectDupKeys");
2206   valid_keys->insert("allowSpecialFloats");
2207 }
2208 bool CharReaderBuilder::validate(Json::Value* invalid) const
2209 {
2210   Json::Value my_invalid;
2211   if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
2212   Json::Value& inv = *invalid;
2213   std::set<JSONCPP_STRING> valid_keys;
2214   getValidReaderKeys(&valid_keys);
2215   Value::Members keys = settings_.getMemberNames();
2216   size_t n = keys.size();
2217   for (size_t i = 0; i < n; ++i) {
2218     JSONCPP_STRING const& key = keys[i];
2219     if (valid_keys.find(key) == valid_keys.end()) {
2220       inv[key] = settings_[key];
2221     }
2222   }
2223   return 0u == inv.size();
2224 }
2225 Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
2226 {
2227   return settings_[key];
2228 }
2229 // static
2230 void CharReaderBuilder::strictMode(Json::Value* settings)
2231 {
2232 //! [CharReaderBuilderStrictMode]
2233   (*settings)["allowComments"] = false;
2234   (*settings)["strictRoot"] = true;
2235   (*settings)["allowDroppedNullPlaceholders"] = false;
2236   (*settings)["allowNumericKeys"] = false;
2237   (*settings)["allowSingleQuotes"] = false;
2238   (*settings)["stackLimit"] = 1000;
2239   (*settings)["failIfExtra"] = true;
2240   (*settings)["rejectDupKeys"] = true;
2241   (*settings)["allowSpecialFloats"] = false;
2242 //! [CharReaderBuilderStrictMode]
2243 }
2244 // static
2245 void CharReaderBuilder::setDefaults(Json::Value* settings)
2246 {
2247 //! [CharReaderBuilderDefaults]
2248   (*settings)["collectComments"] = true;
2249   (*settings)["allowComments"] = true;
2250   (*settings)["strictRoot"] = false;
2251   (*settings)["allowDroppedNullPlaceholders"] = false;
2252   (*settings)["allowNumericKeys"] = false;
2253   (*settings)["allowSingleQuotes"] = false;
2254   (*settings)["stackLimit"] = 1000;
2255   (*settings)["failIfExtra"] = false;
2256   (*settings)["rejectDupKeys"] = false;
2257   (*settings)["allowSpecialFloats"] = false;
2258 //! [CharReaderBuilderDefaults]
2259 }
2260 
2261 //////////////////////////////////
2262 // global functions
2263 
2264 bool parseFromStream(
2265     CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
2266     Value* root, JSONCPP_STRING* errs)
2267 {
2268   JSONCPP_OSTRINGSTREAM ssin;
2269   ssin << sin.rdbuf();
2270   JSONCPP_STRING doc = ssin.str();
2271   char const* begin = doc.data();
2272   char const* end = begin + doc.size();
2273   // Note that we do not actually need a null-terminator.
2274   CharReaderPtr const reader(fact.newCharReader());
2275   return reader->parse(begin, end, root, errs);
2276 }
2277 
2278 JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
2279   CharReaderBuilder b;
2280   JSONCPP_STRING errs;
2281   bool ok = parseFromStream(b, sin, &root, &errs);
2282   if (!ok) {
2283     throwRuntimeError(errs);
2284   }
2285   return sin;
2286 }
2287 
2288 } // namespace Json
2289 
2290 // //////////////////////////////////////////////////////////////////////
2291 // End of content of file: src/lib_json/json_reader.cpp
2292 // //////////////////////////////////////////////////////////////////////
2293 
2294 
2295 
2296 
2297 
2298 
2299 // //////////////////////////////////////////////////////////////////////
2300 // Beginning of content of file: src/lib_json/json_valueiterator.inl
2301 // //////////////////////////////////////////////////////////////////////
2302 
2303 // Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
2304 // Distributed under MIT license, or public domain if desired and
2305 // recognized in your jurisdiction.
2306 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2307 
2308 // included by json_value.cpp
2309 
2310 namespace Json {
2311 
2312 // //////////////////////////////////////////////////////////////////
2313 // //////////////////////////////////////////////////////////////////
2314 // //////////////////////////////////////////////////////////////////
2315 // class ValueIteratorBase
2316 // //////////////////////////////////////////////////////////////////
2317 // //////////////////////////////////////////////////////////////////
2318 // //////////////////////////////////////////////////////////////////
2319 
2320 ValueIteratorBase::ValueIteratorBase()
2321     : current_(), isNull_(true) {
2322 }
2323 
2324 ValueIteratorBase::ValueIteratorBase(
2325     const Value::ObjectValues::iterator& current)
2326     : current_(current), isNull_(false) {}
2327 
2328 Value& ValueIteratorBase::deref() const {
2329   return current_->second;
2330 }
2331 
2332 void ValueIteratorBase::increment() {
2333   ++current_;
2334 }
2335 
2336 void ValueIteratorBase::decrement() {
2337   --current_;
2338 }
2339 
2340 ValueIteratorBase::difference_type
2341 ValueIteratorBase::computeDistance(const SelfType& other) const {
2342 #ifdef JSON_USE_CPPTL_SMALLMAP
2343   return other.current_ - current_;
2344 #else
2345   // Iterator for null value are initialized using the default
2346   // constructor, which initialize current_ to the default
2347   // std::map::iterator. As begin() and end() are two instance
2348   // of the default std::map::iterator, they can not be compared.
2349   // To allow this, we handle this comparison specifically.
2350   if (isNull_ && other.isNull_) {
2351     return 0;
2352   }
2353 
2354   // Usage of std::distance is not portable (does not compile with Sun Studio 12
2355   // RogueWave STL,
2356   // which is the one used by default).
2357   // Using a portable hand-made version for non random iterator instead:
2358   //   return difference_type( std::distance( current_, other.current_ ) );
2359   difference_type myDistance = 0;
2360   for (Value::ObjectValues::iterator it = current_; it != other.current_;
2361        ++it) {
2362     ++myDistance;
2363   }
2364   return myDistance;
2365 #endif
2366 }
2367 
2368 bool ValueIteratorBase::isEqual(const SelfType& other) const {
2369   if (isNull_) {
2370     return other.isNull_;
2371   }
2372   return current_ == other.current_;
2373 }
2374 
2375 void ValueIteratorBase::copy(const SelfType& other) {
2376   current_ = other.current_;
2377   isNull_ = other.isNull_;
2378 }
2379 
2380 Value ValueIteratorBase::key() const {
2381   const Value::CZString czstring = (*current_).first;
2382   if (czstring.data()) {
2383     if (czstring.isStaticString())
2384       return Value(StaticString(czstring.data()));
2385     return Value(czstring.data(), czstring.data() + czstring.length());
2386   }
2387   return Value(czstring.index());
2388 }
2389 
2390 UInt ValueIteratorBase::index() const {
2391   const Value::CZString czstring = (*current_).first;
2392   if (!czstring.data())
2393     return czstring.index();
2394   return Value::UInt(-1);
2395 }
2396 
2397 JSONCPP_STRING ValueIteratorBase::name() const {
2398   char const* keey;
2399   char const* end;
2400   keey = memberName(&end);
2401   if (!keey) return JSONCPP_STRING();
2402   return JSONCPP_STRING(keey, end);
2403 }
2404 
2405 char const* ValueIteratorBase::memberName() const {
2406   const char* cname = (*current_).first.data();
2407   return cname ? cname : "";
2408 }
2409 
2410 char const* ValueIteratorBase::memberName(char const** end) const {
2411   const char* cname = (*current_).first.data();
2412   if (!cname) {
2413     *end = NULL;
2414     return NULL;
2415   }
2416   *end = cname + (*current_).first.length();
2417   return cname;
2418 }
2419 
2420 // //////////////////////////////////////////////////////////////////
2421 // //////////////////////////////////////////////////////////////////
2422 // //////////////////////////////////////////////////////////////////
2423 // class ValueConstIterator
2424 // //////////////////////////////////////////////////////////////////
2425 // //////////////////////////////////////////////////////////////////
2426 // //////////////////////////////////////////////////////////////////
2427 
2428 ValueConstIterator::ValueConstIterator() {}
2429 
2430 ValueConstIterator::ValueConstIterator(
2431     const Value::ObjectValues::iterator& current)
2432     : ValueIteratorBase(current) {}
2433 
2434 ValueConstIterator::ValueConstIterator(ValueIterator const& other)
2435     : ValueIteratorBase(other) {}
2436 
2437 ValueConstIterator& ValueConstIterator::
2438 operator=(const ValueIteratorBase& other) {
2439   copy(other);
2440   return *this;
2441 }
2442 
2443 // //////////////////////////////////////////////////////////////////
2444 // //////////////////////////////////////////////////////////////////
2445 // //////////////////////////////////////////////////////////////////
2446 // class ValueIterator
2447 // //////////////////////////////////////////////////////////////////
2448 // //////////////////////////////////////////////////////////////////
2449 // //////////////////////////////////////////////////////////////////
2450 
2451 ValueIterator::ValueIterator() {}
2452 
2453 ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
2454     : ValueIteratorBase(current) {}
2455 
2456 ValueIterator::ValueIterator(const ValueConstIterator& other)
2457     : ValueIteratorBase(other) {
2458   throwRuntimeError("ConstIterator to Iterator should never be allowed.");
2459 }
2460 
2461 ValueIterator::ValueIterator(const ValueIterator& other)
2462     : ValueIteratorBase(other) {}
2463 
2464 ValueIterator& ValueIterator::operator=(const SelfType& other) {
2465   copy(other);
2466   return *this;
2467 }
2468 
2469 } // namespace Json
2470 
2471 // //////////////////////////////////////////////////////////////////////
2472 // End of content of file: src/lib_json/json_valueiterator.inl
2473 // //////////////////////////////////////////////////////////////////////
2474 
2475 
2476 
2477 
2478 
2479 
2480 // //////////////////////////////////////////////////////////////////////
2481 // Beginning of content of file: src/lib_json/json_value.cpp
2482 // //////////////////////////////////////////////////////////////////////
2483 
2484 // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
2485 // Distributed under MIT license, or public domain if desired and
2486 // recognized in your jurisdiction.
2487 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2488 
2489 #if !defined(JSON_IS_AMALGAMATION)
2490 #include <json/assertions.h>
2491 #include <json/value.h>
2492 #include <json/writer.h>
2493 #endif // if !defined(JSON_IS_AMALGAMATION)
2494 #include <math.h>
2495 #include <sstream>
2496 #include <utility>
2497 #include <cstring>
2498 #include <cassert>
2499 #ifdef JSON_USE_CPPTL
2500 #include <cpptl/conststring.h>
2501 #endif
2502 #include <cstddef> // size_t
2503 #include <algorithm> // min()
2504 
2505 #define JSON_ASSERT_UNREACHABLE assert(false)
2506 
2507 namespace Json {
2508 
2509 // This is a walkaround to avoid the static initialization of Value::null.
2510 // kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
2511 // 8 (instead of 4) as a bit of future-proofing.
2512 #if defined(__ARMEL__)
2513 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
2514 #else
2515 #define ALIGNAS(byte_alignment)
2516 #endif
2517 //static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
2518 //const unsigned char& kNullRef = kNull[0];
2519 //const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
2520 //const Value& Value::nullRef = null;
2521 
2522 // static
2523 Value const& Value::nullSingleton()
2524 {
2525  static Value const nullStatic;
2526  return nullStatic;
2527 }
2528 
2529 // for backwards compatibility, we'll leave these global references around, but DO NOT
2530 // use them in JSONCPP library code any more!
2531 Value const& Value::null = Value::nullSingleton();
2532 Value const& Value::nullRef = Value::nullSingleton();
2533 
2534 const Int Value::minInt = Int(~(UInt(-1) / 2));
2535 const Int Value::maxInt = Int(UInt(-1) / 2);
2536 const UInt Value::maxUInt = UInt(-1);
2537 #if defined(JSON_HAS_INT64)
2538 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
2539 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
2540 const UInt64 Value::maxUInt64 = UInt64(-1);
2541 // The constant is hard-coded because some compiler have trouble
2542 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
2543 // Assumes that UInt64 is a 64 bits integer.
2544 static const double maxUInt64AsDouble = 18446744073709551615.0;
2545 #endif // defined(JSON_HAS_INT64)
2546 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
2547 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
2548 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
2549 
2550 const UInt Value::defaultRealPrecision = 17;
2551 
2552 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2553 template <typename T, typename U>
2554 static inline bool InRange(double d, T min, U max) {
2555   // The casts can lose precision, but we are looking only for
2556   // an approximate range. Might fail on edge cases though. ~cdunn
2557   //return d >= static_cast<double>(min) && d <= static_cast<double>(max);
2558   return d >= min && d <= max;
2559 }
2560 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2561 static inline double integerToDouble(Json::UInt64 value) {
2562   return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
2563 }
2564 
2565 template <typename T> static inline double integerToDouble(T value) {
2566   return static_cast<double>(value);
2567 }
2568 
2569 template <typename T, typename U>
2570 static inline bool InRange(double d, T min, U max) {
2571   return d >= integerToDouble(min) && d <= integerToDouble(max);
2572 }
2573 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2574 
2575 /** Duplicates the specified string value.
2576  * @param value Pointer to the string to duplicate. Must be zero-terminated if
2577  *              length is "unknown".
2578  * @param length Length of the value. if equals to unknown, then it will be
2579  *               computed using strlen(value).
2580  * @return Pointer on the duplicate instance of string.
2581  */
2582 static inline char* duplicateStringValue(const char* value,
2583                                          size_t length)
2584 {
2585   // Avoid an integer overflow in the call to malloc below by limiting length
2586   // to a sane value.
2587   if (length >= static_cast<size_t>(Value::maxInt))
2588     length = Value::maxInt - 1;
2589 
2590   char* newString = static_cast<char*>(malloc(length + 1));
2591   if (newString == NULL) {
2592     throwRuntimeError(
2593         "in Json::Value::duplicateStringValue(): "
2594         "Failed to allocate string value buffer");
2595   }
2596   memcpy(newString, value, length);
2597   newString[length] = 0;
2598   return newString;
2599 }
2600 
2601 /* Record the length as a prefix.
2602  */
2603 static inline char* duplicateAndPrefixStringValue(
2604     const char* value,
2605     unsigned int length)
2606 {
2607   // Avoid an integer overflow in the call to malloc below by limiting length
2608   // to a sane value.
2609   JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
2610                       "in Json::Value::duplicateAndPrefixStringValue(): "
2611                       "length too big for prefixing");
2612   unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
2613   char* newString = static_cast<char*>(malloc(actualLength));
2614   if (newString == 0) {
2615     throwRuntimeError(
2616         "in Json::Value::duplicateAndPrefixStringValue(): "
2617         "Failed to allocate string value buffer");
2618   }
2619   *reinterpret_cast<unsigned*>(newString) = length;
2620   memcpy(newString + sizeof(unsigned), value, length);
2621   newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
2622   return newString;
2623 }
2624 inline static void decodePrefixedString(
2625     bool isPrefixed, char const* prefixed,
2626     unsigned* length, char const** value)
2627 {
2628   if (!isPrefixed) {
2629     *length = static_cast<unsigned>(strlen(prefixed));
2630     *value = prefixed;
2631   } else {
2632     *length = *reinterpret_cast<unsigned const*>(prefixed);
2633     *value = prefixed + sizeof(unsigned);
2634   }
2635 }
2636 /** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
2637  */
2638 #if JSONCPP_USING_SECURE_MEMORY
2639 static inline void releasePrefixedStringValue(char* value) {
2640   unsigned length = 0;
2641   char const* valueDecoded;
2642   decodePrefixedString(true, value, &length, &valueDecoded);
2643   size_t const size = sizeof(unsigned) + length + 1U;
2644   memset(value, 0, size);
2645   free(value);
2646 }
2647 static inline void releaseStringValue(char* value, unsigned length) {
2648   // length==0 => we allocated the strings memory
2649   size_t size = (length==0) ? strlen(value) : length;
2650   memset(value, 0, size);
2651   free(value);
2652 }
2653 #else // !JSONCPP_USING_SECURE_MEMORY
2654 static inline void releasePrefixedStringValue(char* value) {
2655   free(value);
2656 }
2657 static inline void releaseStringValue(char* value, unsigned) {
2658   free(value);
2659 }
2660 #endif // JSONCPP_USING_SECURE_MEMORY
2661 
2662 } // namespace Json
2663 
2664 // //////////////////////////////////////////////////////////////////
2665 // //////////////////////////////////////////////////////////////////
2666 // //////////////////////////////////////////////////////////////////
2667 // ValueInternals...
2668 // //////////////////////////////////////////////////////////////////
2669 // //////////////////////////////////////////////////////////////////
2670 // //////////////////////////////////////////////////////////////////
2671 #if !defined(JSON_IS_AMALGAMATION)
2672 
2673 #include "json_valueiterator.inl"
2674 #endif // if !defined(JSON_IS_AMALGAMATION)
2675 
2676 namespace Json {
2677 
2678 Exception::Exception(JSONCPP_STRING const& msg)
2679   : msg_(msg)
2680 {}
2681 Exception::~Exception() JSONCPP_NOEXCEPT
2682 {}
2683 char const* Exception::what() const JSONCPP_NOEXCEPT
2684 {
2685   return msg_.c_str();
2686 }
2687 RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
2688   : Exception(msg)
2689 {}
2690 LogicError::LogicError(JSONCPP_STRING const& msg)
2691   : Exception(msg)
2692 {}
2693 JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
2694 {
2695   throw RuntimeError(msg);
2696 }
2697 JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
2698 {
2699   throw LogicError(msg);
2700 }
2701 
2702 // //////////////////////////////////////////////////////////////////
2703 // //////////////////////////////////////////////////////////////////
2704 // //////////////////////////////////////////////////////////////////
2705 // class Value::CommentInfo
2706 // //////////////////////////////////////////////////////////////////
2707 // //////////////////////////////////////////////////////////////////
2708 // //////////////////////////////////////////////////////////////////
2709 
2710 Value::CommentInfo::CommentInfo() : comment_(0)
2711 {}
2712 
2713 Value::CommentInfo::~CommentInfo() {
2714   if (comment_)
2715     releaseStringValue(comment_, 0u);
2716 }
2717 
2718 void Value::CommentInfo::setComment(const char* text, size_t len) {
2719   if (comment_) {
2720     releaseStringValue(comment_, 0u);
2721     comment_ = 0;
2722   }
2723   JSON_ASSERT(text != 0);
2724   JSON_ASSERT_MESSAGE(
2725       text[0] == '\0' || text[0] == '/',
2726       "in Json::Value::setComment(): Comments must start with /");
2727   // It seems that /**/ style comments are acceptable as well.
2728   comment_ = duplicateStringValue(text, len);
2729 }
2730 
2731 // //////////////////////////////////////////////////////////////////
2732 // //////////////////////////////////////////////////////////////////
2733 // //////////////////////////////////////////////////////////////////
2734 // class Value::CZString
2735 // //////////////////////////////////////////////////////////////////
2736 // //////////////////////////////////////////////////////////////////
2737 // //////////////////////////////////////////////////////////////////
2738 
2739 // Notes: policy_ indicates if the string was allocated when
2740 // a string is stored.
2741 
2742 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
2743 
2744 Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
2745     : cstr_(str) {
2746   // allocate != duplicate
2747   storage_.policy_ = allocate & 0x3;
2748   storage_.length_ = ulength & 0x3FFFFFFF;
2749 }
2750 
2751 Value::CZString::CZString(const CZString& other) {
2752   cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
2753                  ? duplicateStringValue(other.cstr_, other.storage_.length_)
2754                  : other.cstr_);
2755   storage_.policy_ = static_cast<unsigned>(other.cstr_
2756                  ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
2757                      ? noDuplication : duplicate)
2758                  : static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
2759   storage_.length_ = other.storage_.length_;
2760 }
2761 
2762 #if JSON_HAS_RVALUE_REFERENCES
2763 Value::CZString::CZString(CZString&& other)
2764   : cstr_(other.cstr_), index_(other.index_) {
2765   other.cstr_ = nullptr;
2766 }
2767 #endif
2768 
2769 Value::CZString::~CZString() {
2770   if (cstr_ && storage_.policy_ == duplicate) {
2771       releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
2772   }
2773 }
2774 
2775 void Value::CZString::swap(CZString& other) {
2776   std::swap(cstr_, other.cstr_);
2777   std::swap(index_, other.index_);
2778 }
2779 
2780 Value::CZString& Value::CZString::operator=(const CZString& other) {
2781   cstr_ = other.cstr_;
2782   index_ = other.index_;
2783   return *this;
2784 }
2785 
2786 #if JSON_HAS_RVALUE_REFERENCES
2787 Value::CZString& Value::CZString::operator=(CZString&& other) {
2788   cstr_ = other.cstr_;
2789   index_ = other.index_;
2790   other.cstr_ = nullptr;
2791   return *this;
2792 }
2793 #endif
2794 
2795 bool Value::CZString::operator<(const CZString& other) const {
2796   if (!cstr_) return index_ < other.index_;
2797   //return strcmp(cstr_, other.cstr_) < 0;
2798   // Assume both are strings.
2799   unsigned this_len = this->storage_.length_;
2800   unsigned other_len = other.storage_.length_;
2801   unsigned min_len = std::min<unsigned>(this_len, other_len);
2802   JSON_ASSERT(this->cstr_ && other.cstr_);
2803   int comp = memcmp(this->cstr_, other.cstr_, min_len);
2804   if (comp < 0) return true;
2805   if (comp > 0) return false;
2806   return (this_len < other_len);
2807 }
2808 
2809 bool Value::CZString::operator==(const CZString& other) const {
2810   if (!cstr_) return index_ == other.index_;
2811   //return strcmp(cstr_, other.cstr_) == 0;
2812   // Assume both are strings.
2813   unsigned this_len = this->storage_.length_;
2814   unsigned other_len = other.storage_.length_;
2815   if (this_len != other_len) return false;
2816   JSON_ASSERT(this->cstr_ && other.cstr_);
2817   int comp = memcmp(this->cstr_, other.cstr_, this_len);
2818   return comp == 0;
2819 }
2820 
2821 ArrayIndex Value::CZString::index() const { return index_; }
2822 
2823 //const char* Value::CZString::c_str() const { return cstr_; }
2824 const char* Value::CZString::data() const { return cstr_; }
2825 unsigned Value::CZString::length() const { return storage_.length_; }
2826 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
2827 
2828 // //////////////////////////////////////////////////////////////////
2829 // //////////////////////////////////////////////////////////////////
2830 // //////////////////////////////////////////////////////////////////
2831 // class Value::Value
2832 // //////////////////////////////////////////////////////////////////
2833 // //////////////////////////////////////////////////////////////////
2834 // //////////////////////////////////////////////////////////////////
2835 
2836 /*! \internal Default constructor initialization must be equivalent to:
2837  * memset( this, 0, sizeof(Value) )
2838  * This optimization is used in ValueInternalMap fast allocator.
2839  */
2840 Value::Value(ValueType vtype) {
2841   static char const emptyString[] = "";
2842   initBasic(vtype);
2843   switch (vtype) {
2844   case nullValue:
2845     break;
2846   case intValue:
2847   case uintValue:
2848     value_.int_ = 0;
2849     break;
2850   case realValue:
2851     value_.real_ = 0.0;
2852     break;
2853   case stringValue:
2854     // allocated_ == false, so this is safe.
2855     value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
2856     break;
2857   case arrayValue:
2858   case objectValue:
2859     value_.map_ = new ObjectValues();
2860     break;
2861   case booleanValue:
2862     value_.bool_ = false;
2863     break;
2864   default:
2865     JSON_ASSERT_UNREACHABLE;
2866   }
2867 }
2868 
2869 Value::Value(Int value) {
2870   initBasic(intValue);
2871   value_.int_ = value;
2872 }
2873 
2874 Value::Value(UInt value) {
2875   initBasic(uintValue);
2876   value_.uint_ = value;
2877 }
2878 #if defined(JSON_HAS_INT64)
2879 Value::Value(Int64 value) {
2880   initBasic(intValue);
2881   value_.int_ = value;
2882 }
2883 Value::Value(UInt64 value) {
2884   initBasic(uintValue);
2885   value_.uint_ = value;
2886 }
2887 #endif // defined(JSON_HAS_INT64)
2888 
2889 Value::Value(double value) {
2890   initBasic(realValue);
2891   value_.real_ = value;
2892 }
2893 
2894 Value::Value(const char* value) {
2895   initBasic(stringValue, true);
2896   JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
2897   value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
2898 }
2899 
2900 Value::Value(const char* beginValue, const char* endValue) {
2901   initBasic(stringValue, true);
2902   value_.string_ =
2903       duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
2904 }
2905 
2906 Value::Value(const JSONCPP_STRING& value) {
2907   initBasic(stringValue, true);
2908   value_.string_ =
2909       duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
2910 }
2911 
2912 Value::Value(const StaticString& value) {
2913   initBasic(stringValue);
2914   value_.string_ = const_cast<char*>(value.c_str());
2915 }
2916 
2917 #ifdef JSON_USE_CPPTL
2918 Value::Value(const CppTL::ConstString& value) {
2919   initBasic(stringValue, true);
2920   value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
2921 }
2922 #endif
2923 
2924 Value::Value(bool value) {
2925   initBasic(booleanValue);
2926   value_.bool_ = value;
2927 }
2928 
2929 Value::Value(const Value& other) {
2930   dupPayload(other);
2931   dupMeta(other);
2932 }
2933 
2934 #if JSON_HAS_RVALUE_REFERENCES
2935 // Move constructor
2936 Value::Value(Value&& other) {
2937   initBasic(nullValue);
2938   swap(other);
2939 }
2940 #endif
2941 
2942 Value::~Value() {
2943   releasePayload();
2944 
2945   delete[] comments_;
2946 
2947   value_.uint_ = 0;
2948 }
2949 
2950 Value& Value::operator=(Value other) {
2951   swap(other);
2952   return *this;
2953 }
2954 
2955 void Value::swapPayload(Value& other) {
2956   ValueType temp = type_;
2957   type_ = other.type_;
2958   other.type_ = temp;
2959   std::swap(value_, other.value_);
2960   int temp2 = allocated_;
2961   allocated_ = other.allocated_;
2962   other.allocated_ = temp2 & 0x1;
2963 }
2964 
2965 void Value::copyPayload(const Value& other) {
2966   releasePayload();
2967   dupPayload(other);
2968 }
2969 
2970 void Value::swap(Value& other) {
2971   swapPayload(other);
2972   std::swap(comments_, other.comments_);
2973   std::swap(start_, other.start_);
2974   std::swap(limit_, other.limit_);
2975 }
2976 
2977 void Value::copy(const Value& other) {
2978   copyPayload(other);
2979   delete[] comments_;
2980   dupMeta(other);
2981 }
2982 
2983 ValueType Value::type() const { return type_; }
2984 
2985 int Value::compare(const Value& other) const {
2986   if (*this < other)
2987     return -1;
2988   if (*this > other)
2989     return 1;
2990   return 0;
2991 }
2992 
2993 bool Value::operator<(const Value& other) const {
2994   int typeDelta = type_ - other.type_;
2995   if (typeDelta)
2996     return typeDelta < 0 ? true : false;
2997   switch (type_) {
2998   case nullValue:
2999     return false;
3000   case intValue:
3001     return value_.int_ < other.value_.int_;
3002   case uintValue:
3003     return value_.uint_ < other.value_.uint_;
3004   case realValue:
3005     return value_.real_ < other.value_.real_;
3006   case booleanValue:
3007     return value_.bool_ < other.value_.bool_;
3008   case stringValue:
3009   {
3010     if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
3011       if (other.value_.string_) return true;
3012       else return false;
3013     }
3014     unsigned this_len;
3015     unsigned other_len;
3016     char const* this_str;
3017     char const* other_str;
3018     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3019     decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3020     unsigned min_len = std::min<unsigned>(this_len, other_len);
3021     JSON_ASSERT(this_str && other_str);
3022     int comp = memcmp(this_str, other_str, min_len);
3023     if (comp < 0) return true;
3024     if (comp > 0) return false;
3025     return (this_len < other_len);
3026   }
3027   case arrayValue:
3028   case objectValue: {
3029     int delta = int(value_.map_->size() - other.value_.map_->size());
3030     if (delta)
3031       return delta < 0;
3032     return (*value_.map_) < (*other.value_.map_);
3033   }
3034   default:
3035     JSON_ASSERT_UNREACHABLE;
3036   }
3037   return false; // unreachable
3038 }
3039 
3040 bool Value::operator<=(const Value& other) const { return !(other < *this); }
3041 
3042 bool Value::operator>=(const Value& other) const { return !(*this < other); }
3043 
3044 bool Value::operator>(const Value& other) const { return other < *this; }
3045 
3046 bool Value::operator==(const Value& other) const {
3047   // if ( type_ != other.type_ )
3048   // GCC 2.95.3 says:
3049   // attempt to take address of bit-field structure member `Json::Value::type_'
3050   // Beats me, but a temp solves the problem.
3051   int temp = other.type_;
3052   if (type_ != temp)
3053     return false;
3054   switch (type_) {
3055   case nullValue:
3056     return true;
3057   case intValue:
3058     return value_.int_ == other.value_.int_;
3059   case uintValue:
3060     return value_.uint_ == other.value_.uint_;
3061   case realValue:
3062     return value_.real_ == other.value_.real_;
3063   case booleanValue:
3064     return value_.bool_ == other.value_.bool_;
3065   case stringValue:
3066   {
3067     if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
3068       return (value_.string_ == other.value_.string_);
3069     }
3070     unsigned this_len;
3071     unsigned other_len;
3072     char const* this_str;
3073     char const* other_str;
3074     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3075     decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3076     if (this_len != other_len) return false;
3077     JSON_ASSERT(this_str && other_str);
3078     int comp = memcmp(this_str, other_str, this_len);
3079     return comp == 0;
3080   }
3081   case arrayValue:
3082   case objectValue:
3083     return value_.map_->size() == other.value_.map_->size() &&
3084            (*value_.map_) == (*other.value_.map_);
3085   default:
3086     JSON_ASSERT_UNREACHABLE;
3087   }
3088   return false; // unreachable
3089 }
3090 
3091 bool Value::operator!=(const Value& other) const { return !(*this == other); }
3092 
3093 const char* Value::asCString() const {
3094   JSON_ASSERT_MESSAGE(type_ == stringValue,
3095                       "in Json::Value::asCString(): requires stringValue");
3096   if (value_.string_ == 0) return 0;
3097   unsigned this_len;
3098   char const* this_str;
3099   decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3100   return this_str;
3101 }
3102 
3103 #if JSONCPP_USING_SECURE_MEMORY
3104 unsigned Value::getCStringLength() const {
3105   JSON_ASSERT_MESSAGE(type_ == stringValue,
3106                       "in Json::Value::asCString(): requires stringValue");
3107   if (value_.string_ == 0) return 0;
3108   unsigned this_len;
3109   char const* this_str;
3110   decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3111   return this_len;
3112 }
3113 #endif
3114 
3115 bool Value::getString(char const** str, char const** cend) const {
3116   if (type_ != stringValue) return false;
3117   if (value_.string_ == 0) return false;
3118   unsigned length;
3119   decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
3120   *cend = *str + length;
3121   return true;
3122 }
3123 
3124 JSONCPP_STRING Value::asString() const {
3125   switch (type_) {
3126   case nullValue:
3127     return "";
3128   case stringValue:
3129   {
3130     if (value_.string_ == 0) return "";
3131     unsigned this_len;
3132     char const* this_str;
3133     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3134     return JSONCPP_STRING(this_str, this_len);
3135   }
3136   case booleanValue:
3137     return value_.bool_ ? "true" : "false";
3138   case intValue:
3139     return valueToString(value_.int_);
3140   case uintValue:
3141     return valueToString(value_.uint_);
3142   case realValue:
3143     return valueToString(value_.real_);
3144   default:
3145     JSON_FAIL_MESSAGE("Type is not convertible to string");
3146   }
3147 }
3148 
3149 #ifdef JSON_USE_CPPTL
3150 CppTL::ConstString Value::asConstString() const {
3151   unsigned len;
3152   char const* str;
3153   decodePrefixedString(allocated_, value_.string_,
3154       &len, &str);
3155   return CppTL::ConstString(str, len);
3156 }
3157 #endif
3158 
3159 Value::Int Value::asInt() const {
3160   switch (type_) {
3161   case intValue:
3162     JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
3163     return Int(value_.int_);
3164   case uintValue:
3165     JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
3166     return Int(value_.uint_);
3167   case realValue:
3168     JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
3169                         "double out of Int range");
3170     return Int(value_.real_);
3171   case nullValue:
3172     return 0;
3173   case booleanValue:
3174     return value_.bool_ ? 1 : 0;
3175   default:
3176     break;
3177   }
3178   JSON_FAIL_MESSAGE("Value is not convertible to Int.");
3179 }
3180 
3181 Value::UInt Value::asUInt() const {
3182   switch (type_) {
3183   case intValue:
3184     JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
3185     return UInt(value_.int_);
3186   case uintValue:
3187     JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
3188     return UInt(value_.uint_);
3189   case realValue:
3190     JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
3191                         "double out of UInt range");
3192     return UInt(value_.real_);
3193   case nullValue:
3194     return 0;
3195   case booleanValue:
3196     return value_.bool_ ? 1 : 0;
3197   default:
3198     break;
3199   }
3200   JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
3201 }
3202 
3203 #if defined(JSON_HAS_INT64)
3204 
3205 Value::Int64 Value::asInt64() const {
3206   switch (type_) {
3207   case intValue:
3208     return Int64(value_.int_);
3209   case uintValue:
3210     JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
3211     return Int64(value_.uint_);
3212   case realValue:
3213     JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
3214                         "double out of Int64 range");
3215     return Int64(value_.real_);
3216   case nullValue:
3217     return 0;
3218   case booleanValue:
3219     return value_.bool_ ? 1 : 0;
3220   default:
3221     break;
3222   }
3223   JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
3224 }
3225 
3226 Value::UInt64 Value::asUInt64() const {
3227   switch (type_) {
3228   case intValue:
3229     JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
3230     return UInt64(value_.int_);
3231   case uintValue:
3232     return UInt64(value_.uint_);
3233   case realValue:
3234     JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
3235                         "double out of UInt64 range");
3236     return UInt64(value_.real_);
3237   case nullValue:
3238     return 0;
3239   case booleanValue:
3240     return value_.bool_ ? 1 : 0;
3241   default:
3242     break;
3243   }
3244   JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
3245 }
3246 #endif // if defined(JSON_HAS_INT64)
3247 
3248 LargestInt Value::asLargestInt() const {
3249 #if defined(JSON_NO_INT64)
3250   return asInt();
3251 #else
3252   return asInt64();
3253 #endif
3254 }
3255 
3256 LargestUInt Value::asLargestUInt() const {
3257 #if defined(JSON_NO_INT64)
3258   return asUInt();
3259 #else
3260   return asUInt64();
3261 #endif
3262 }
3263 
3264 double Value::asDouble() const {
3265   switch (type_) {
3266   case intValue:
3267     return static_cast<double>(value_.int_);
3268   case uintValue:
3269 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3270     return static_cast<double>(value_.uint_);
3271 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3272     return integerToDouble(value_.uint_);
3273 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3274   case realValue:
3275     return value_.real_;
3276   case nullValue:
3277     return 0.0;
3278   case booleanValue:
3279     return value_.bool_ ? 1.0 : 0.0;
3280   default:
3281     break;
3282   }
3283   JSON_FAIL_MESSAGE("Value is not convertible to double.");
3284 }
3285 
3286 float Value::asFloat() const {
3287   switch (type_) {
3288   case intValue:
3289     return static_cast<float>(value_.int_);
3290   case uintValue:
3291 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3292     return static_cast<float>(value_.uint_);
3293 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3294     // This can fail (silently?) if the value is bigger than MAX_FLOAT.
3295     return static_cast<float>(integerToDouble(value_.uint_));
3296 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3297   case realValue:
3298     return static_cast<float>(value_.real_);
3299   case nullValue:
3300     return 0.0;
3301   case booleanValue:
3302     return value_.bool_ ? 1.0f : 0.0f;
3303   default:
3304     break;
3305   }
3306   JSON_FAIL_MESSAGE("Value is not convertible to float.");
3307 }
3308 
3309 bool Value::asBool() const {
3310   switch (type_) {
3311   case booleanValue:
3312     return value_.bool_;
3313   case nullValue:
3314     return false;
3315   case intValue:
3316     return value_.int_ ? true : false;
3317   case uintValue:
3318     return value_.uint_ ? true : false;
3319   case realValue:
3320     // This is kind of strange. Not recommended.
3321     return (value_.real_ != 0.0) ? true : false;
3322   default:
3323     break;
3324   }
3325   JSON_FAIL_MESSAGE("Value is not convertible to bool.");
3326 }
3327 
3328 bool Value::isConvertibleTo(ValueType other) const {
3329   switch (other) {
3330   case nullValue:
3331     return (isNumeric() && asDouble() == 0.0) ||
3332            (type_ == booleanValue && value_.bool_ == false) ||
3333            (type_ == stringValue && asString().empty()) ||
3334            (type_ == arrayValue && value_.map_->size() == 0) ||
3335            (type_ == objectValue && value_.map_->size() == 0) ||
3336            type_ == nullValue;
3337   case intValue:
3338     return isInt() ||
3339            (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
3340            type_ == booleanValue || type_ == nullValue;
3341   case uintValue:
3342     return isUInt() ||
3343            (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
3344            type_ == booleanValue || type_ == nullValue;
3345   case realValue:
3346     return isNumeric() || type_ == booleanValue || type_ == nullValue;
3347   case booleanValue:
3348     return isNumeric() || type_ == booleanValue || type_ == nullValue;
3349   case stringValue:
3350     return isNumeric() || type_ == booleanValue || type_ == stringValue ||
3351            type_ == nullValue;
3352   case arrayValue:
3353     return type_ == arrayValue || type_ == nullValue;
3354   case objectValue:
3355     return type_ == objectValue || type_ == nullValue;
3356   }
3357   JSON_ASSERT_UNREACHABLE;
3358   return false;
3359 }
3360 
3361 /// Number of values in array or object
3362 ArrayIndex Value::size() const {
3363   switch (type_) {
3364   case nullValue:
3365   case intValue:
3366   case uintValue:
3367   case realValue:
3368   case booleanValue:
3369   case stringValue:
3370     return 0;
3371   case arrayValue: // size of the array is highest index + 1
3372     if (!value_.map_->empty()) {
3373       ObjectValues::const_iterator itLast = value_.map_->end();
3374       --itLast;
3375       return (*itLast).first.index() + 1;
3376     }
3377     return 0;
3378   case objectValue:
3379     return ArrayIndex(value_.map_->size());
3380   }
3381   JSON_ASSERT_UNREACHABLE;
3382   return 0; // unreachable;
3383 }
3384 
3385 bool Value::empty() const {
3386   if (isNull() || isArray() || isObject())
3387     return size() == 0u;
3388   else
3389     return false;
3390 }
3391 
3392 Value::operator bool() const { return ! isNull(); }
3393 
3394 void Value::clear() {
3395   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
3396                           type_ == objectValue,
3397                       "in Json::Value::clear(): requires complex value");
3398   start_ = 0;
3399   limit_ = 0;
3400   switch (type_) {
3401   case arrayValue:
3402   case objectValue:
3403     value_.map_->clear();
3404     break;
3405   default:
3406     break;
3407   }
3408 }
3409 
3410 void Value::resize(ArrayIndex newSize) {
3411   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3412                       "in Json::Value::resize(): requires arrayValue");
3413   if (type_ == nullValue)
3414     *this = Value(arrayValue);
3415   ArrayIndex oldSize = size();
3416   if (newSize == 0)
3417     clear();
3418   else if (newSize > oldSize)
3419     this->operator[](newSize - 1);
3420   else {
3421     for (ArrayIndex index = newSize; index < oldSize; ++index) {
3422       value_.map_->erase(index);
3423     }
3424     JSON_ASSERT(size() == newSize);
3425   }
3426 }
3427 
3428 Value& Value::operator[](ArrayIndex index) {
3429   JSON_ASSERT_MESSAGE(
3430       type_ == nullValue || type_ == arrayValue,
3431       "in Json::Value::operator[](ArrayIndex): requires arrayValue");
3432   if (type_ == nullValue)
3433     *this = Value(arrayValue);
3434   CZString key(index);
3435   ObjectValues::iterator it = value_.map_->lower_bound(key);
3436   if (it != value_.map_->end() && (*it).first == key)
3437     return (*it).second;
3438 
3439   ObjectValues::value_type defaultValue(key, nullSingleton());
3440   it = value_.map_->insert(it, defaultValue);
3441   return (*it).second;
3442 }
3443 
3444 Value& Value::operator[](int index) {
3445   JSON_ASSERT_MESSAGE(
3446       index >= 0,
3447       "in Json::Value::operator[](int index): index cannot be negative");
3448   return (*this)[ArrayIndex(index)];
3449 }
3450 
3451 const Value& Value::operator[](ArrayIndex index) const {
3452   JSON_ASSERT_MESSAGE(
3453       type_ == nullValue || type_ == arrayValue,
3454       "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
3455   if (type_ == nullValue)
3456     return nullSingleton();
3457   CZString key(index);
3458   ObjectValues::const_iterator it = value_.map_->find(key);
3459   if (it == value_.map_->end())
3460     return nullSingleton();
3461   return (*it).second;
3462 }
3463 
3464 const Value& Value::operator[](int index) const {
3465   JSON_ASSERT_MESSAGE(
3466       index >= 0,
3467       "in Json::Value::operator[](int index) const: index cannot be negative");
3468   return (*this)[ArrayIndex(index)];
3469 }
3470 
3471 void Value::initBasic(ValueType vtype, bool allocated) {
3472   type_ = vtype;
3473   allocated_ = allocated;
3474   comments_ = 0;
3475   start_ = 0;
3476   limit_ = 0;
3477 }
3478 
3479 void Value::dupPayload(const Value& other) {
3480   type_ = other.type_;
3481   allocated_ = false;
3482   switch (type_) {
3483   case nullValue:
3484   case intValue:
3485   case uintValue:
3486   case realValue:
3487   case booleanValue:
3488     value_ = other.value_;
3489     break;
3490   case stringValue:
3491     if (other.value_.string_ && other.allocated_) {
3492       unsigned len;
3493       char const* str;
3494       decodePrefixedString(other.allocated_, other.value_.string_,
3495           &len, &str);
3496       value_.string_ = duplicateAndPrefixStringValue(str, len);
3497       allocated_ = true;
3498     } else {
3499       value_.string_ = other.value_.string_;
3500     }
3501     break;
3502   case arrayValue:
3503   case objectValue:
3504     value_.map_ = new ObjectValues(*other.value_.map_);
3505     break;
3506   default:
3507     JSON_ASSERT_UNREACHABLE;
3508   }
3509 }
3510 
3511 void Value::releasePayload() {
3512   switch (type_) {
3513   case nullValue:
3514   case intValue:
3515   case uintValue:
3516   case realValue:
3517   case booleanValue:
3518     break;
3519   case stringValue:
3520     if (allocated_)
3521       releasePrefixedStringValue(value_.string_);
3522     break;
3523   case arrayValue:
3524   case objectValue:
3525     delete value_.map_;
3526     break;
3527   default:
3528     JSON_ASSERT_UNREACHABLE;
3529   }
3530 }
3531 
3532 void Value::dupMeta(const Value& other) {
3533   if (other.comments_) {
3534     comments_ = new CommentInfo[numberOfCommentPlacement];
3535     for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
3536       const CommentInfo& otherComment = other.comments_[comment];
3537       if (otherComment.comment_)
3538         comments_[comment].setComment(
3539             otherComment.comment_, strlen(otherComment.comment_));
3540     }
3541   } else {
3542     comments_ = 0;
3543   }
3544   start_ = other.start_;
3545   limit_ = other.limit_;
3546 }
3547 
3548 // Access an object value by name, create a null member if it does not exist.
3549 // @pre Type of '*this' is object or null.
3550 // @param key is null-terminated.
3551 Value& Value::resolveReference(const char* key) {
3552   JSON_ASSERT_MESSAGE(
3553       type_ == nullValue || type_ == objectValue,
3554       "in Json::Value::resolveReference(): requires objectValue");
3555   if (type_ == nullValue)
3556     *this = Value(objectValue);
3557   CZString actualKey(
3558       key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
3559   ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3560   if (it != value_.map_->end() && (*it).first == actualKey)
3561     return (*it).second;
3562 
3563   ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3564   it = value_.map_->insert(it, defaultValue);
3565   Value& value = (*it).second;
3566   return value;
3567 }
3568 
3569 // @param key is not null-terminated.
3570 Value& Value::resolveReference(char const* key, char const* cend)
3571 {
3572   JSON_ASSERT_MESSAGE(
3573       type_ == nullValue || type_ == objectValue,
3574       "in Json::Value::resolveReference(key, end): requires objectValue");
3575   if (type_ == nullValue)
3576     *this = Value(objectValue);
3577   CZString actualKey(
3578       key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
3579   ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3580   if (it != value_.map_->end() && (*it).first == actualKey)
3581     return (*it).second;
3582 
3583   ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3584   it = value_.map_->insert(it, defaultValue);
3585   Value& value = (*it).second;
3586   return value;
3587 }
3588 
3589 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
3590   const Value* value = &((*this)[index]);
3591   return value == &nullSingleton() ? defaultValue : *value;
3592 }
3593 
3594 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
3595 
3596 Value const* Value::find(char const* key, char const* cend) const
3597 {
3598   JSON_ASSERT_MESSAGE(
3599       type_ == nullValue || type_ == objectValue,
3600       "in Json::Value::find(key, end, found): requires objectValue or nullValue");
3601   if (type_ == nullValue) return NULL;
3602   CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3603   ObjectValues::const_iterator it = value_.map_->find(actualKey);
3604   if (it == value_.map_->end()) return NULL;
3605   return &(*it).second;
3606 }
3607 const Value& Value::operator[](const char* key) const
3608 {
3609   Value const* found = find(key, key + strlen(key));
3610   if (!found) return nullSingleton();
3611   return *found;
3612 }
3613 Value const& Value::operator[](JSONCPP_STRING const& key) const
3614 {
3615   Value const* found = find(key.data(), key.data() + key.length());
3616   if (!found) return nullSingleton();
3617   return *found;
3618 }
3619 
3620 Value& Value::operator[](const char* key) {
3621   return resolveReference(key, key + strlen(key));
3622 }
3623 
3624 Value& Value::operator[](const JSONCPP_STRING& key) {
3625   return resolveReference(key.data(), key.data() + key.length());
3626 }
3627 
3628 Value& Value::operator[](const StaticString& key) {
3629   return resolveReference(key.c_str());
3630 }
3631 
3632 #ifdef JSON_USE_CPPTL
3633 Value& Value::operator[](const CppTL::ConstString& key) {
3634   return resolveReference(key.c_str(), key.end_c_str());
3635 }
3636 Value const& Value::operator[](CppTL::ConstString const& key) const
3637 {
3638   Value const* found = find(key.c_str(), key.end_c_str());
3639   if (!found) return nullSingleton();
3640   return *found;
3641 }
3642 #endif
3643 
3644 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
3645 
3646 #if JSON_HAS_RVALUE_REFERENCES
3647   Value& Value::append(Value&& value) { return (*this)[size()] = std::move(value); }
3648 #endif
3649 
3650 Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
3651 {
3652   Value const* found = find(key, cend);
3653   return !found ? defaultValue : *found;
3654 }
3655 Value Value::get(char const* key, Value const& defaultValue) const
3656 {
3657   return get(key, key + strlen(key), defaultValue);
3658 }
3659 Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
3660 {
3661   return get(key.data(), key.data() + key.length(), defaultValue);
3662 }
3663 
3664 
3665 bool Value::removeMember(const char* key, const char* cend, Value* removed)
3666 {
3667   if (type_ != objectValue) {
3668     return false;
3669   }
3670   CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3671   ObjectValues::iterator it = value_.map_->find(actualKey);
3672   if (it == value_.map_->end())
3673     return false;
3674   if (removed)
3675 #if JSON_HAS_RVALUE_REFERENCES
3676     *removed = std::move(it->second);
3677 #else
3678     *removed = it->second;
3679 #endif
3680   value_.map_->erase(it);
3681   return true;
3682 }
3683 bool Value::removeMember(const char* key, Value* removed)
3684 {
3685   return removeMember(key, key + strlen(key), removed);
3686 }
3687 bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
3688 {
3689   return removeMember(key.data(), key.data() + key.length(), removed);
3690 }
3691 void Value::removeMember(const char* key)
3692 {
3693   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3694                       "in Json::Value::removeMember(): requires objectValue");
3695   if (type_ == nullValue)
3696     return;
3697 
3698   CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
3699   value_.map_->erase(actualKey);
3700 }
3701 void Value::removeMember(const JSONCPP_STRING& key)
3702 {
3703   removeMember(key.c_str());
3704 }
3705 
3706 bool Value::removeIndex(ArrayIndex index, Value* removed) {
3707   if (type_ != arrayValue) {
3708     return false;
3709   }
3710   CZString key(index);
3711   ObjectValues::iterator it = value_.map_->find(key);
3712   if (it == value_.map_->end()) {
3713     return false;
3714   }
3715   *removed = it->second;
3716   ArrayIndex oldSize = size();
3717   // shift left all items left, into the place of the "removed"
3718   for (ArrayIndex i = index; i < (oldSize - 1); ++i){
3719     CZString keey(i);
3720     (*value_.map_)[keey] = (*this)[i + 1];
3721   }
3722   // erase the last one ("leftover")
3723   CZString keyLast(oldSize - 1);
3724   ObjectValues::iterator itLast = value_.map_->find(keyLast);
3725   value_.map_->erase(itLast);
3726   return true;
3727 }
3728 
3729 #ifdef JSON_USE_CPPTL
3730 Value Value::get(const CppTL::ConstString& key,
3731                  const Value& defaultValue) const {
3732   return get(key.c_str(), key.end_c_str(), defaultValue);
3733 }
3734 #endif
3735 
3736 bool Value::isMember(char const* key, char const* cend) const
3737 {
3738   Value const* value = find(key, cend);
3739   return NULL != value;
3740 }
3741 bool Value::isMember(char const* key) const
3742 {
3743   return isMember(key, key + strlen(key));
3744 }
3745 bool Value::isMember(JSONCPP_STRING const& key) const
3746 {
3747   return isMember(key.data(), key.data() + key.length());
3748 }
3749 
3750 #ifdef JSON_USE_CPPTL
3751 bool Value::isMember(const CppTL::ConstString& key) const {
3752   return isMember(key.c_str(), key.end_c_str());
3753 }
3754 #endif
3755 
3756 Value::Members Value::getMemberNames() const {
3757   JSON_ASSERT_MESSAGE(
3758       type_ == nullValue || type_ == objectValue,
3759       "in Json::Value::getMemberNames(), value must be objectValue");
3760   if (type_ == nullValue)
3761     return Value::Members();
3762   Members members;
3763   members.reserve(value_.map_->size());
3764   ObjectValues::const_iterator it = value_.map_->begin();
3765   ObjectValues::const_iterator itEnd = value_.map_->end();
3766   for (; it != itEnd; ++it) {
3767     members.push_back(JSONCPP_STRING((*it).first.data(),
3768                                   (*it).first.length()));
3769   }
3770   return members;
3771 }
3772 //
3773 //# ifdef JSON_USE_CPPTL
3774 // EnumMemberNames
3775 // Value::enumMemberNames() const
3776 //{
3777 //   if ( type_ == objectValue )
3778 //   {
3779 //      return CppTL::Enum::any(  CppTL::Enum::transform(
3780 //         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
3781 //         MemberNamesTransform() ) );
3782 //   }
3783 //   return EnumMemberNames();
3784 //}
3785 //
3786 //
3787 // EnumValues
3788 // Value::enumValues() const
3789 //{
3790 //   if ( type_ == objectValue  ||  type_ == arrayValue )
3791 //      return CppTL::Enum::anyValues( *(value_.map_),
3792 //                                     CppTL::Type<const Value &>() );
3793 //   return EnumValues();
3794 //}
3795 //
3796 //# endif
3797 
3798 static bool IsIntegral(double d) {
3799   double integral_part;
3800   return modf(d, &integral_part) == 0.0;
3801 }
3802 
3803 bool Value::isNull() const { return type_ == nullValue; }
3804 
3805 bool Value::isBool() const { return type_ == booleanValue; }
3806 
3807 bool Value::isInt() const {
3808   switch (type_) {
3809   case intValue:
3810 #if defined(JSON_HAS_INT64)
3811     return value_.int_ >= minInt && value_.int_ <= maxInt;
3812 #else
3813     return true;
3814 #endif
3815   case uintValue:
3816     return value_.uint_ <= UInt(maxInt);
3817   case realValue:
3818     return value_.real_ >= minInt && value_.real_ <= maxInt &&
3819            IsIntegral(value_.real_);
3820   default:
3821     break;
3822   }
3823   return false;
3824 }
3825 
3826 bool Value::isUInt() const {
3827   switch (type_) {
3828   case intValue:
3829 #if defined(JSON_HAS_INT64)
3830     return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
3831 #else
3832     return value_.int_ >= 0;
3833 #endif
3834   case uintValue:
3835 #if defined(JSON_HAS_INT64)
3836     return value_.uint_ <= maxUInt;
3837 #else
3838     return true;
3839 #endif
3840   case realValue:
3841     return value_.real_ >= 0 && value_.real_ <= maxUInt &&
3842            IsIntegral(value_.real_);
3843   default:
3844     break;
3845   }
3846   return false;
3847 }
3848 
3849 bool Value::isInt64() const {
3850 #if defined(JSON_HAS_INT64)
3851   switch (type_) {
3852   case intValue:
3853     return true;
3854   case uintValue:
3855     return value_.uint_ <= UInt64(maxInt64);
3856   case realValue:
3857     // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
3858     // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
3859     // require the value to be strictly less than the limit.
3860     return value_.real_ >= double(minInt64) &&
3861            value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
3862   default:
3863     break;
3864   }
3865 #endif // JSON_HAS_INT64
3866   return false;
3867 }
3868 
3869 bool Value::isUInt64() const {
3870 #if defined(JSON_HAS_INT64)
3871   switch (type_) {
3872   case intValue:
3873     return value_.int_ >= 0;
3874   case uintValue:
3875     return true;
3876   case realValue:
3877     // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3878     // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3879     // require the value to be strictly less than the limit.
3880     return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
3881            IsIntegral(value_.real_);
3882   default:
3883     break;
3884   }
3885 #endif // JSON_HAS_INT64
3886   return false;
3887 }
3888 
3889 bool Value::isIntegral() const {
3890   switch (type_) {
3891     case intValue:
3892     case uintValue:
3893       return true;
3894     case realValue:
3895 #if defined(JSON_HAS_INT64)
3896       // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3897       // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3898       // require the value to be strictly less than the limit.
3899       return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
3900 #else
3901       return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
3902 #endif // JSON_HAS_INT64
3903     default:
3904       break;
3905   }
3906   return false;
3907 }
3908 
3909 bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
3910 
3911 bool Value::isNumeric() const { return isDouble(); }
3912 
3913 bool Value::isString() const { return type_ == stringValue; }
3914 
3915 bool Value::isArray() const { return type_ == arrayValue; }
3916 
3917 bool Value::isObject() const { return type_ == objectValue; }
3918 
3919 void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
3920   if (!comments_)
3921     comments_ = new CommentInfo[numberOfCommentPlacement];
3922   if ((len > 0) && (comment[len-1] == '\n')) {
3923     // Always discard trailing newline, to aid indentation.
3924     len -= 1;
3925   }
3926   comments_[placement].setComment(comment, len);
3927 }
3928 
3929 void Value::setComment(const char* comment, CommentPlacement placement) {
3930   setComment(comment, strlen(comment), placement);
3931 }
3932 
3933 void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
3934   setComment(comment.c_str(), comment.length(), placement);
3935 }
3936 
3937 bool Value::hasComment(CommentPlacement placement) const {
3938   return comments_ != 0 && comments_[placement].comment_ != 0;
3939 }
3940 
3941 JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
3942   if (hasComment(placement))
3943     return comments_[placement].comment_;
3944   return "";
3945 }
3946 
3947 void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
3948 
3949 void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
3950 
3951 ptrdiff_t Value::getOffsetStart() const { return start_; }
3952 
3953 ptrdiff_t Value::getOffsetLimit() const { return limit_; }
3954 
3955 JSONCPP_STRING Value::toStyledString() const {
3956   StreamWriterBuilder builder;
3957 
3958   JSONCPP_STRING out = this->hasComment(commentBefore) ? "\n" : "";
3959   out += Json::writeString(builder, *this);
3960   out += "\n";
3961 
3962   return out;
3963 }
3964 
3965 Value::const_iterator Value::begin() const {
3966   switch (type_) {
3967   case arrayValue:
3968   case objectValue:
3969     if (value_.map_)
3970       return const_iterator(value_.map_->begin());
3971     break;
3972   default:
3973     break;
3974   }
3975   return const_iterator();
3976 }
3977 
3978 Value::const_iterator Value::end() const {
3979   switch (type_) {
3980   case arrayValue:
3981   case objectValue:
3982     if (value_.map_)
3983       return const_iterator(value_.map_->end());
3984     break;
3985   default:
3986     break;
3987   }
3988   return const_iterator();
3989 }
3990 
3991 Value::iterator Value::begin() {
3992   switch (type_) {
3993   case arrayValue:
3994   case objectValue:
3995     if (value_.map_)
3996       return iterator(value_.map_->begin());
3997     break;
3998   default:
3999     break;
4000   }
4001   return iterator();
4002 }
4003 
4004 Value::iterator Value::end() {
4005   switch (type_) {
4006   case arrayValue:
4007   case objectValue:
4008     if (value_.map_)
4009       return iterator(value_.map_->end());
4010     break;
4011   default:
4012     break;
4013   }
4014   return iterator();
4015 }
4016 
4017 // class PathArgument
4018 // //////////////////////////////////////////////////////////////////
4019 
4020 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
4021 
4022 PathArgument::PathArgument(ArrayIndex index)
4023     : key_(), index_(index), kind_(kindIndex) {}
4024 
4025 PathArgument::PathArgument(const char* key)
4026     : key_(key), index_(), kind_(kindKey) {}
4027 
4028 PathArgument::PathArgument(const JSONCPP_STRING& key)
4029     : key_(key.c_str()), index_(), kind_(kindKey) {}
4030 
4031 // class Path
4032 // //////////////////////////////////////////////////////////////////
4033 
4034 Path::Path(const JSONCPP_STRING& path,
4035            const PathArgument& a1,
4036            const PathArgument& a2,
4037            const PathArgument& a3,
4038            const PathArgument& a4,
4039            const PathArgument& a5) {
4040   InArgs in;
4041   in.reserve(5);
4042   in.push_back(&a1);
4043   in.push_back(&a2);
4044   in.push_back(&a3);
4045   in.push_back(&a4);
4046   in.push_back(&a5);
4047   makePath(path, in);
4048 }
4049 
4050 void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
4051   const char* current = path.c_str();
4052   const char* end = current + path.length();
4053   InArgs::const_iterator itInArg = in.begin();
4054   while (current != end) {
4055     if (*current == '[') {
4056       ++current;
4057       if (*current == '%')
4058         addPathInArg(path, in, itInArg, PathArgument::kindIndex);
4059       else {
4060         ArrayIndex index = 0;
4061         for (; current != end && *current >= '0' && *current <= '9'; ++current)
4062           index = index * 10 + ArrayIndex(*current - '0');
4063         args_.push_back(index);
4064       }
4065       if (current == end || *++current != ']')
4066         invalidPath(path, int(current - path.c_str()));
4067     } else if (*current == '%') {
4068       addPathInArg(path, in, itInArg, PathArgument::kindKey);
4069       ++current;
4070     } else if (*current == '.' || *current == ']') {
4071       ++current;
4072     } else {
4073       const char* beginName = current;
4074       while (current != end && !strchr("[.", *current))
4075         ++current;
4076       args_.push_back(JSONCPP_STRING(beginName, current));
4077     }
4078   }
4079 }
4080 
4081 void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
4082                         const InArgs& in,
4083                         InArgs::const_iterator& itInArg,
4084                         PathArgument::Kind kind) {
4085   if (itInArg == in.end()) {
4086     // Error: missing argument %d
4087   } else if ((*itInArg)->kind_ != kind) {
4088     // Error: bad argument type
4089   } else {
4090     args_.push_back(**itInArg++);
4091   }
4092 }
4093 
4094 void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
4095   // Error: invalid path.
4096 }
4097 
4098 const Value& Path::resolve(const Value& root) const {
4099   const Value* node = &root;
4100   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4101     const PathArgument& arg = *it;
4102     if (arg.kind_ == PathArgument::kindIndex) {
4103       if (!node->isArray() || !node->isValidIndex(arg.index_)) {
4104         // Error: unable to resolve path (array value expected at position...
4105         return Value::null;
4106       }
4107       node = &((*node)[arg.index_]);
4108     } else if (arg.kind_ == PathArgument::kindKey) {
4109       if (!node->isObject()) {
4110         // Error: unable to resolve path (object value expected at position...)
4111         return Value::null;
4112       }
4113       node = &((*node)[arg.key_]);
4114       if (node == &Value::nullSingleton()) {
4115         // Error: unable to resolve path (object has no member named '' at
4116         // position...)
4117         return Value::null;
4118       }
4119     }
4120   }
4121   return *node;
4122 }
4123 
4124 Value Path::resolve(const Value& root, const Value& defaultValue) const {
4125   const Value* node = &root;
4126   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4127     const PathArgument& arg = *it;
4128     if (arg.kind_ == PathArgument::kindIndex) {
4129       if (!node->isArray() || !node->isValidIndex(arg.index_))
4130         return defaultValue;
4131       node = &((*node)[arg.index_]);
4132     } else if (arg.kind_ == PathArgument::kindKey) {
4133       if (!node->isObject())
4134         return defaultValue;
4135       node = &((*node)[arg.key_]);
4136       if (node == &Value::nullSingleton())
4137         return defaultValue;
4138     }
4139   }
4140   return *node;
4141 }
4142 
4143 Value& Path::make(Value& root) const {
4144   Value* node = &root;
4145   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
4146     const PathArgument& arg = *it;
4147     if (arg.kind_ == PathArgument::kindIndex) {
4148       if (!node->isArray()) {
4149         // Error: node is not an array at position ...
4150       }
4151       node = &((*node)[arg.index_]);
4152     } else if (arg.kind_ == PathArgument::kindKey) {
4153       if (!node->isObject()) {
4154         // Error: node is not an object at position...
4155       }
4156       node = &((*node)[arg.key_]);
4157     }
4158   }
4159   return *node;
4160 }
4161 
4162 } // namespace Json
4163 
4164 // //////////////////////////////////////////////////////////////////////
4165 // End of content of file: src/lib_json/json_value.cpp
4166 // //////////////////////////////////////////////////////////////////////
4167 
4168 
4169 
4170 
4171 
4172 
4173 // //////////////////////////////////////////////////////////////////////
4174 // Beginning of content of file: src/lib_json/json_writer.cpp
4175 // //////////////////////////////////////////////////////////////////////
4176 
4177 // Copyright 2011 Baptiste Lepilleur and The JsonCpp Authors
4178 // Distributed under MIT license, or public domain if desired and
4179 // recognized in your jurisdiction.
4180 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
4181 
4182 #if !defined(JSON_IS_AMALGAMATION)
4183 #include <json/writer.h>
4184 #include "json_tool.h"
4185 #endif // if !defined(JSON_IS_AMALGAMATION)
4186 #include <iomanip>
4187 #include <memory>
4188 #include <sstream>
4189 #include <utility>
4190 #include <set>
4191 #include <cassert>
4192 #include <cstring>
4193 #include <cstdio>
4194 
4195 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
4196 #include <float.h>
4197 #define isfinite _finite
4198 #elif defined(__sun) && defined(__SVR4) //Solaris
4199 #if !defined(isfinite)
4200 #include <ieeefp.h>
4201 #define isfinite finite
4202 #endif
4203 #elif defined(_AIX)
4204 #if !defined(isfinite)
4205 #include <math.h>
4206 #define isfinite finite
4207 #endif
4208 #elif defined(__hpux)
4209 #if !defined(isfinite)
4210 #if defined(__ia64) && !defined(finite)
4211 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \
4212                      _Isfinitef(x) : _IsFinite(x)))
4213 #else
4214 #include <math.h>
4215 #define isfinite finite
4216 #endif
4217 #endif
4218 #else
4219 #include <cmath>
4220 #if !(defined(__QNXNTO__)) // QNX already defines isfinite
4221 #define isfinite std::isfinite
4222 #endif
4223 #endif
4224 
4225 #if defined(_MSC_VER)
4226 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
4227 #define snprintf sprintf_s
4228 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
4229 #define snprintf std::snprintf
4230 #else
4231 #define snprintf _snprintf
4232 #endif
4233 #elif defined(__ANDROID__) || defined(__QNXNTO__)
4234 #define snprintf snprintf
4235 #elif __cplusplus >= 201103L
4236 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
4237 #define snprintf std::snprintf
4238 #endif
4239 #endif
4240 
4241 #if defined(__BORLANDC__)  
4242 #include <float.h>
4243 #define isfinite _finite
4244 #define snprintf _snprintf
4245 #endif
4246 
4247 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
4248 // Disable warning about strdup being deprecated.
4249 #pragma warning(disable : 4996)
4250 #endif
4251 
4252 namespace Json {
4253 
4254 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
4255 typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
4256 #else
4257 typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
4258 #endif
4259 
4260 JSONCPP_STRING valueToString(LargestInt value) {
4261   UIntToStringBuffer buffer;
4262   char* current = buffer + sizeof(buffer);
4263   if (value == Value::minLargestInt) {
4264     uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
4265     *--current = '-';
4266   } else if (value < 0) {
4267     uintToString(LargestUInt(-value), current);
4268     *--current = '-';
4269   } else {
4270     uintToString(LargestUInt(value), current);
4271   }
4272   assert(current >= buffer);
4273   return current;
4274 }
4275 
4276 JSONCPP_STRING valueToString(LargestUInt value) {
4277   UIntToStringBuffer buffer;
4278   char* current = buffer + sizeof(buffer);
4279   uintToString(value, current);
4280   assert(current >= buffer);
4281   return current;
4282 }
4283 
4284 #if defined(JSON_HAS_INT64)
4285 
4286 JSONCPP_STRING valueToString(Int value) {
4287   return valueToString(LargestInt(value));
4288 }
4289 
4290 JSONCPP_STRING valueToString(UInt value) {
4291   return valueToString(LargestUInt(value));
4292 }
4293 
4294 #endif // # if defined(JSON_HAS_INT64)
4295 
4296 namespace {
4297 JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision, PrecisionType precisionType) {
4298   // Allocate a buffer that is more than large enough to store the 16 digits of
4299   // precision requested below.
4300   char buffer[36];
4301   int len = -1;
4302 
4303   char formatString[15];
4304   if (precisionType == PrecisionType::significantDigits) {
4305     snprintf(formatString, sizeof(formatString), "%%.%ug", precision);
4306   } else {
4307     snprintf(formatString, sizeof(formatString), "%%.%uf", precision);
4308   }
4309 
4310   // Print into the buffer. We need not request the alternative representation
4311   // that always has a decimal point because JSON doesn't distinguish the
4312   // concepts of reals and integers.
4313   if (isfinite(value)) {
4314     len = snprintf(buffer, sizeof(buffer), formatString, value);
4315     fixNumericLocale(buffer, buffer + len);
4316     // to delete use-less too much zeros in the end of string
4317     if (precisionType == PrecisionType::decimalPlaces) {
4318       fixZerosInTheEnd(buffer, buffer + len);
4319     }
4320 
4321     // try to ensure we preserve the fact that this was given to us as a double on input
4322     if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
4323       strcat(buffer, ".0");
4324     }
4325 
4326   } else {
4327     // IEEE standard states that NaN values will not compare to themselves
4328     if (value != value) {
4329       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
4330     } else if (value < 0) {
4331       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
4332     } else {
4333       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
4334     }
4335   }
4336   assert(len >= 0);
4337   return buffer;
4338 }
4339 }
4340 
4341 JSONCPP_STRING valueToString(double value, unsigned int precision, PrecisionType precisionType) {
4342   return valueToString(value, false, precision, precisionType);
4343 }
4344 
4345 JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
4346 
4347 static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
4348   assert(s || !n);
4349 
4350   char const* const end = s + n;
4351   for (char const* cur = s; cur < end; ++cur) {
4352     if (*cur == '\\' || *cur == '\"' || *cur < ' '
4353       || static_cast<unsigned char>(*cur) < 0x80)
4354       return true;
4355   }
4356   return false;
4357 }
4358 
4359 static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
4360   const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
4361 
4362   unsigned int firstByte = static_cast<unsigned char>(*s);
4363 
4364   if (firstByte < 0x80)
4365     return firstByte;
4366 
4367   if (firstByte < 0xE0) {
4368     if (e - s < 2)
4369       return REPLACEMENT_CHARACTER;
4370 
4371     unsigned int calculated = ((firstByte & 0x1F) << 6)
4372       | (static_cast<unsigned int>(s[1]) & 0x3F);
4373     s += 1;
4374     // oversized encoded characters are invalid
4375     return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
4376   }
4377 
4378   if (firstByte < 0xF0) {
4379     if (e - s < 3)
4380       return REPLACEMENT_CHARACTER;
4381 
4382     unsigned int calculated = ((firstByte & 0x0F) << 12)
4383       | ((static_cast<unsigned int>(s[1]) & 0x3F) << 6)
4384       |  (static_cast<unsigned int>(s[2]) & 0x3F);
4385     s += 2;
4386     // surrogates aren't valid codepoints itself
4387     // shouldn't be UTF-8 encoded
4388     if (calculated >= 0xD800 && calculated <= 0xDFFF)
4389       return REPLACEMENT_CHARACTER;
4390     // oversized encoded characters are invalid
4391     return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
4392   }
4393 
4394   if (firstByte < 0xF8) {
4395     if (e - s < 4)
4396       return REPLACEMENT_CHARACTER;
4397 
4398     unsigned int calculated = ((firstByte & 0x07) << 18)
4399       | ((static_cast<unsigned int>(s[1]) & 0x3F) << 12)
4400       | ((static_cast<unsigned int>(s[2]) & 0x3F) << 6)
4401       |  (static_cast<unsigned int>(s[3]) & 0x3F);
4402     s += 3;
4403     // oversized encoded characters are invalid
4404     return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
4405   }
4406 
4407   return REPLACEMENT_CHARACTER;
4408 }
4409 
4410 static const char hex2[] =
4411   "000102030405060708090a0b0c0d0e0f"
4412   "101112131415161718191a1b1c1d1e1f"
4413   "202122232425262728292a2b2c2d2e2f"
4414   "303132333435363738393a3b3c3d3e3f"
4415   "404142434445464748494a4b4c4d4e4f"
4416   "505152535455565758595a5b5c5d5e5f"
4417   "606162636465666768696a6b6c6d6e6f"
4418   "707172737475767778797a7b7c7d7e7f"
4419   "808182838485868788898a8b8c8d8e8f"
4420   "909192939495969798999a9b9c9d9e9f"
4421   "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
4422   "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
4423   "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
4424   "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
4425   "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
4426   "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
4427 
4428 static JSONCPP_STRING toHex16Bit(unsigned int x) {
4429   const unsigned int hi = (x >> 8) & 0xff;
4430   const unsigned int lo = x & 0xff;
4431   JSONCPP_STRING result(4, ' ');
4432   result[0] = hex2[2 * hi];
4433   result[1] = hex2[2 * hi + 1];
4434   result[2] = hex2[2 * lo];
4435   result[3] = hex2[2 * lo + 1];
4436   return result;
4437 }
4438 
4439 static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
4440   if (value == NULL)
4441     return "";
4442 
4443   if (!isAnyCharRequiredQuoting(value, length))
4444     return JSONCPP_STRING("\"") + value + "\"";
4445   // We have to walk value and escape any special characters.
4446   // Appending to JSONCPP_STRING is not efficient, but this should be rare.
4447   // (Note: forward slashes are *not* rare, but I am not escaping them.)
4448   JSONCPP_STRING::size_type maxsize =
4449       length * 2 + 3; // allescaped+quotes+NULL
4450   JSONCPP_STRING result;
4451   result.reserve(maxsize); // to avoid lots of mallocs
4452   result += "\"";
4453   char const* end = value + length;
4454   for (const char* c = value; c != end; ++c) {
4455     switch (*c) {
4456     case '\"':
4457       result += "\\\"";
4458       break;
4459     case '\\':
4460       result += "\\\\";
4461       break;
4462     case '\b':
4463       result += "\\b";
4464       break;
4465     case '\f':
4466       result += "\\f";
4467       break;
4468     case '\n':
4469       result += "\\n";
4470       break;
4471     case '\r':
4472       result += "\\r";
4473       break;
4474     case '\t':
4475       result += "\\t";
4476       break;
4477     // case '/':
4478     // Even though \/ is considered a legal escape in JSON, a bare
4479     // slash is also legal, so I see no reason to escape it.
4480     // (I hope I am not misunderstanding something.)
4481     // blep notes: actually escaping \/ may be useful in javascript to avoid </
4482     // sequence.
4483     // Should add a flag to allow this compatibility mode and prevent this
4484     // sequence from occurring.
4485     default: {
4486         unsigned int cp = utf8ToCodepoint(c, end);
4487         // don't escape non-control characters
4488         // (short escape sequence are applied above)
4489         if (cp < 0x80 && cp >= 0x20)
4490           result += static_cast<char>(cp);
4491         else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
4492           result += "\\u";
4493           result += toHex16Bit(cp);
4494         }
4495         else { // codepoint is not in Basic Multilingual Plane
4496                // convert to surrogate pair first
4497           cp -= 0x10000;
4498           result += "\\u";
4499           result += toHex16Bit((cp >> 10) + 0xD800);
4500           result += "\\u";
4501           result += toHex16Bit((cp & 0x3FF) + 0xDC00);
4502         }
4503       }
4504       break;
4505     }
4506   }
4507   result += "\"";
4508   return result;
4509 }
4510 
4511 JSONCPP_STRING valueToQuotedString(const char* value) {
4512   return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
4513 }
4514 
4515 // Class Writer
4516 // //////////////////////////////////////////////////////////////////
4517 Writer::~Writer() {}
4518 
4519 // Class FastWriter
4520 // //////////////////////////////////////////////////////////////////
4521 
4522 FastWriter::FastWriter()
4523     : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
4524       omitEndingLineFeed_(false) {}
4525 
4526 void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
4527 
4528 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
4529 
4530 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
4531 
4532 JSONCPP_STRING FastWriter::write(const Value& root) {
4533   document_.clear();
4534   writeValue(root);
4535   if (!omitEndingLineFeed_)
4536     document_ += "\n";
4537   return document_;
4538 }
4539 
4540 void FastWriter::writeValue(const Value& value) {
4541   switch (value.type()) {
4542   case nullValue:
4543     if (!dropNullPlaceholders_)
4544       document_ += "null";
4545     break;
4546   case intValue:
4547     document_ += valueToString(value.asLargestInt());
4548     break;
4549   case uintValue:
4550     document_ += valueToString(value.asLargestUInt());
4551     break;
4552   case realValue:
4553     document_ += valueToString(value.asDouble());
4554     break;
4555   case stringValue:
4556   {
4557     // Is NULL possible for value.string_? No.
4558     char const* str;
4559     char const* end;
4560     bool ok = value.getString(&str, &end);
4561     if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
4562     break;
4563   }
4564   case booleanValue:
4565     document_ += valueToString(value.asBool());
4566     break;
4567   case arrayValue: {
4568     document_ += '[';
4569     ArrayIndex size = value.size();
4570     for (ArrayIndex index = 0; index < size; ++index) {
4571       if (index > 0)
4572         document_ += ',';
4573       writeValue(value[index]);
4574     }
4575     document_ += ']';
4576   } break;
4577   case objectValue: {
4578     Value::Members members(value.getMemberNames());
4579     document_ += '{';
4580     for (Value::Members::iterator it = members.begin(); it != members.end();
4581          ++it) {
4582       const JSONCPP_STRING& name = *it;
4583       if (it != members.begin())
4584         document_ += ',';
4585       document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
4586       document_ += yamlCompatibilityEnabled_ ? ": " : ":";
4587       writeValue(value[name]);
4588     }
4589     document_ += '}';
4590   } break;
4591   }
4592 }
4593 
4594 // Class StyledWriter
4595 // //////////////////////////////////////////////////////////////////
4596 
4597 StyledWriter::StyledWriter()
4598     : rightMargin_(74), indentSize_(3), addChildValues_() {}
4599 
4600 JSONCPP_STRING StyledWriter::write(const Value& root) {
4601   document_.clear();
4602   addChildValues_ = false;
4603   indentString_.clear();
4604   writeCommentBeforeValue(root);
4605   writeValue(root);
4606   writeCommentAfterValueOnSameLine(root);
4607   document_ += "\n";
4608   return document_;
4609 }
4610 
4611 void StyledWriter::writeValue(const Value& value) {
4612   switch (value.type()) {
4613   case nullValue:
4614     pushValue("null");
4615     break;
4616   case intValue:
4617     pushValue(valueToString(value.asLargestInt()));
4618     break;
4619   case uintValue:
4620     pushValue(valueToString(value.asLargestUInt()));
4621     break;
4622   case realValue:
4623     pushValue(valueToString(value.asDouble()));
4624     break;
4625   case stringValue:
4626   {
4627     // Is NULL possible for value.string_? No.
4628     char const* str;
4629     char const* end;
4630     bool ok = value.getString(&str, &end);
4631     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4632     else pushValue("");
4633     break;
4634   }
4635   case booleanValue:
4636     pushValue(valueToString(value.asBool()));
4637     break;
4638   case arrayValue:
4639     writeArrayValue(value);
4640     break;
4641   case objectValue: {
4642     Value::Members members(value.getMemberNames());
4643     if (members.empty())
4644       pushValue("{}");
4645     else {
4646       writeWithIndent("{");
4647       indent();
4648       Value::Members::iterator it = members.begin();
4649       for (;;) {
4650         const JSONCPP_STRING& name = *it;
4651         const Value& childValue = value[name];
4652         writeCommentBeforeValue(childValue);
4653         writeWithIndent(valueToQuotedString(name.c_str()));
4654         document_ += " : ";
4655         writeValue(childValue);
4656         if (++it == members.end()) {
4657           writeCommentAfterValueOnSameLine(childValue);
4658           break;
4659         }
4660         document_ += ',';
4661         writeCommentAfterValueOnSameLine(childValue);
4662       }
4663       unindent();
4664       writeWithIndent("}");
4665     }
4666   } break;
4667   }
4668 }
4669 
4670 void StyledWriter::writeArrayValue(const Value& value) {
4671   unsigned size = value.size();
4672   if (size == 0)
4673     pushValue("[]");
4674   else {
4675     bool isArrayMultiLine = isMultilineArray(value);
4676     if (isArrayMultiLine) {
4677       writeWithIndent("[");
4678       indent();
4679       bool hasChildValue = !childValues_.empty();
4680       unsigned index = 0;
4681       for (;;) {
4682         const Value& childValue = value[index];
4683         writeCommentBeforeValue(childValue);
4684         if (hasChildValue)
4685           writeWithIndent(childValues_[index]);
4686         else {
4687           writeIndent();
4688           writeValue(childValue);
4689         }
4690         if (++index == size) {
4691           writeCommentAfterValueOnSameLine(childValue);
4692           break;
4693         }
4694         document_ += ',';
4695         writeCommentAfterValueOnSameLine(childValue);
4696       }
4697       unindent();
4698       writeWithIndent("]");
4699     } else // output on a single line
4700     {
4701       assert(childValues_.size() == size);
4702       document_ += "[ ";
4703       for (unsigned index = 0; index < size; ++index) {
4704         if (index > 0)
4705           document_ += ", ";
4706         document_ += childValues_[index];
4707       }
4708       document_ += " ]";
4709     }
4710   }
4711 }
4712 
4713 bool StyledWriter::isMultilineArray(const Value& value) {
4714   ArrayIndex const size = value.size();
4715   bool isMultiLine = size * 3 >= rightMargin_;
4716   childValues_.clear();
4717   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
4718     const Value& childValue = value[index];
4719     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4720                         childValue.size() > 0);
4721   }
4722   if (!isMultiLine) // check if line length > max line length
4723   {
4724     childValues_.reserve(size);
4725     addChildValues_ = true;
4726     ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4727     for (ArrayIndex index = 0; index < size; ++index) {
4728       if (hasCommentForValue(value[index])) {
4729         isMultiLine = true;
4730       }
4731       writeValue(value[index]);
4732       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
4733     }
4734     addChildValues_ = false;
4735     isMultiLine = isMultiLine || lineLength >= rightMargin_;
4736   }
4737   return isMultiLine;
4738 }
4739 
4740 void StyledWriter::pushValue(const JSONCPP_STRING& value) {
4741   if (addChildValues_)
4742     childValues_.push_back(value);
4743   else
4744     document_ += value;
4745 }
4746 
4747 void StyledWriter::writeIndent() {
4748   if (!document_.empty()) {
4749     char last = document_[document_.length() - 1];
4750     if (last == ' ') // already indented
4751       return;
4752     if (last != '\n') // Comments may add new-line
4753       document_ += '\n';
4754   }
4755   document_ += indentString_;
4756 }
4757 
4758 void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
4759   writeIndent();
4760   document_ += value;
4761 }
4762 
4763 void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
4764 
4765 void StyledWriter::unindent() {
4766   assert(indentString_.size() >= indentSize_);
4767   indentString_.resize(indentString_.size() - indentSize_);
4768 }
4769 
4770 void StyledWriter::writeCommentBeforeValue(const Value& root) {
4771   if (!root.hasComment(commentBefore))
4772     return;
4773 
4774   document_ += "\n";
4775   writeIndent();
4776   const JSONCPP_STRING& comment = root.getComment(commentBefore);
4777   JSONCPP_STRING::const_iterator iter = comment.begin();
4778   while (iter != comment.end()) {
4779     document_ += *iter;
4780     if (*iter == '\n' &&
4781        ((iter+1) != comment.end() && *(iter + 1) == '/'))
4782       writeIndent();
4783     ++iter;
4784   }
4785 
4786   // Comments are stripped of trailing newlines, so add one here
4787   document_ += "\n";
4788 }
4789 
4790 void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
4791   if (root.hasComment(commentAfterOnSameLine))
4792     document_ += " " + root.getComment(commentAfterOnSameLine);
4793 
4794   if (root.hasComment(commentAfter)) {
4795     document_ += "\n";
4796     document_ += root.getComment(commentAfter);
4797     document_ += "\n";
4798   }
4799 }
4800 
4801 bool StyledWriter::hasCommentForValue(const Value& value) {
4802   return value.hasComment(commentBefore) ||
4803          value.hasComment(commentAfterOnSameLine) ||
4804          value.hasComment(commentAfter);
4805 }
4806 
4807 // Class StyledStreamWriter
4808 // //////////////////////////////////////////////////////////////////
4809 
4810 StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
4811     : document_(NULL), rightMargin_(74), indentation_(indentation),
4812       addChildValues_(), indented_(false)
4813 {}
4814 
4815 void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
4816   document_ = &out;
4817   addChildValues_ = false;
4818   indentString_.clear();
4819   indented_ = true;
4820   writeCommentBeforeValue(root);
4821   if (!indented_) writeIndent();
4822   indented_ = true;
4823   writeValue(root);
4824   writeCommentAfterValueOnSameLine(root);
4825   *document_ << "\n";
4826   document_ = NULL; // Forget the stream, for safety.
4827 }
4828 
4829 void StyledStreamWriter::writeValue(const Value& value) {
4830   switch (value.type()) {
4831   case nullValue:
4832     pushValue("null");
4833     break;
4834   case intValue:
4835     pushValue(valueToString(value.asLargestInt()));
4836     break;
4837   case uintValue:
4838     pushValue(valueToString(value.asLargestUInt()));
4839     break;
4840   case realValue:
4841     pushValue(valueToString(value.asDouble()));
4842     break;
4843   case stringValue:
4844   {
4845     // Is NULL possible for value.string_? No.
4846     char const* str;
4847     char const* end;
4848     bool ok = value.getString(&str, &end);
4849     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4850     else pushValue("");
4851     break;
4852   }
4853   case booleanValue:
4854     pushValue(valueToString(value.asBool()));
4855     break;
4856   case arrayValue:
4857     writeArrayValue(value);
4858     break;
4859   case objectValue: {
4860     Value::Members members(value.getMemberNames());
4861     if (members.empty())
4862       pushValue("{}");
4863     else {
4864       writeWithIndent("{");
4865       indent();
4866       Value::Members::iterator it = members.begin();
4867       for (;;) {
4868         const JSONCPP_STRING& name = *it;
4869         const Value& childValue = value[name];
4870         writeCommentBeforeValue(childValue);
4871         writeWithIndent(valueToQuotedString(name.c_str()));
4872         *document_ << " : ";
4873         writeValue(childValue);
4874         if (++it == members.end()) {
4875           writeCommentAfterValueOnSameLine(childValue);
4876           break;
4877         }
4878         *document_ << ",";
4879         writeCommentAfterValueOnSameLine(childValue);
4880       }
4881       unindent();
4882       writeWithIndent("}");
4883     }
4884   } break;
4885   }
4886 }
4887 
4888 void StyledStreamWriter::writeArrayValue(const Value& value) {
4889   unsigned size = value.size();
4890   if (size == 0)
4891     pushValue("[]");
4892   else {
4893     bool isArrayMultiLine = isMultilineArray(value);
4894     if (isArrayMultiLine) {
4895       writeWithIndent("[");
4896       indent();
4897       bool hasChildValue = !childValues_.empty();
4898       unsigned index = 0;
4899       for (;;) {
4900         const Value& childValue = value[index];
4901         writeCommentBeforeValue(childValue);
4902         if (hasChildValue)
4903           writeWithIndent(childValues_[index]);
4904         else {
4905           if (!indented_) writeIndent();
4906           indented_ = true;
4907           writeValue(childValue);
4908           indented_ = false;
4909         }
4910         if (++index == size) {
4911           writeCommentAfterValueOnSameLine(childValue);
4912           break;
4913         }
4914         *document_ << ",";
4915         writeCommentAfterValueOnSameLine(childValue);
4916       }
4917       unindent();
4918       writeWithIndent("]");
4919     } else // output on a single line
4920     {
4921       assert(childValues_.size() == size);
4922       *document_ << "[ ";
4923       for (unsigned index = 0; index < size; ++index) {
4924         if (index > 0)
4925           *document_ << ", ";
4926         *document_ << childValues_[index];
4927       }
4928       *document_ << " ]";
4929     }
4930   }
4931 }
4932 
4933 bool StyledStreamWriter::isMultilineArray(const Value& value) {
4934   ArrayIndex const size = value.size();
4935   bool isMultiLine = size * 3 >= rightMargin_;
4936   childValues_.clear();
4937   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
4938     const Value& childValue = value[index];
4939     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4940                         childValue.size() > 0);
4941   }
4942   if (!isMultiLine) // check if line length > max line length
4943   {
4944     childValues_.reserve(size);
4945     addChildValues_ = true;
4946     ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4947     for (ArrayIndex index = 0; index < size; ++index) {
4948       if (hasCommentForValue(value[index])) {
4949         isMultiLine = true;
4950       }
4951       writeValue(value[index]);
4952       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
4953     }
4954     addChildValues_ = false;
4955     isMultiLine = isMultiLine || lineLength >= rightMargin_;
4956   }
4957   return isMultiLine;
4958 }
4959 
4960 void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
4961   if (addChildValues_)
4962     childValues_.push_back(value);
4963   else
4964     *document_ << value;
4965 }
4966 
4967 void StyledStreamWriter::writeIndent() {
4968   // blep intended this to look at the so-far-written string
4969   // to determine whether we are already indented, but
4970   // with a stream we cannot do that. So we rely on some saved state.
4971   // The caller checks indented_.
4972   *document_ << '\n' << indentString_;
4973 }
4974 
4975 void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
4976   if (!indented_) writeIndent();
4977   *document_ << value;
4978   indented_ = false;
4979 }
4980 
4981 void StyledStreamWriter::indent() { indentString_ += indentation_; }
4982 
4983 void StyledStreamWriter::unindent() {
4984   assert(indentString_.size() >= indentation_.size());
4985   indentString_.resize(indentString_.size() - indentation_.size());
4986 }
4987 
4988 void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
4989   if (!root.hasComment(commentBefore))
4990     return;
4991 
4992   if (!indented_) writeIndent();
4993   const JSONCPP_STRING& comment = root.getComment(commentBefore);
4994   JSONCPP_STRING::const_iterator iter = comment.begin();
4995   while (iter != comment.end()) {
4996     *document_ << *iter;
4997     if (*iter == '\n' &&
4998        ((iter+1) != comment.end() && *(iter + 1) == '/'))
4999       // writeIndent();  // would include newline
5000       *document_ << indentString_;
5001     ++iter;
5002   }
5003   indented_ = false;
5004 }
5005 
5006 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
5007   if (root.hasComment(commentAfterOnSameLine))
5008     *document_ << ' ' << root.getComment(commentAfterOnSameLine);
5009 
5010   if (root.hasComment(commentAfter)) {
5011     writeIndent();
5012     *document_ << root.getComment(commentAfter);
5013   }
5014   indented_ = false;
5015 }
5016 
5017 bool StyledStreamWriter::hasCommentForValue(const Value& value) {
5018   return value.hasComment(commentBefore) ||
5019          value.hasComment(commentAfterOnSameLine) ||
5020          value.hasComment(commentAfter);
5021 }
5022 
5023 //////////////////////////
5024 // BuiltStyledStreamWriter
5025 
5026 /// Scoped enums are not available until C++11.
5027 struct CommentStyle {
5028   /// Decide whether to write comments.
5029   enum Enum {
5030     None,  ///< Drop all comments.
5031     Most,  ///< Recover odd behavior of previous versions (not implemented yet).
5032     All  ///< Keep all comments.
5033   };
5034 };
5035 
5036 struct BuiltStyledStreamWriter : public StreamWriter
5037 {
5038   BuiltStyledStreamWriter(
5039       JSONCPP_STRING const& indentation,
5040       CommentStyle::Enum cs,
5041       JSONCPP_STRING const& colonSymbol,
5042       JSONCPP_STRING const& nullSymbol,
5043       JSONCPP_STRING const& endingLineFeedSymbol,
5044       bool useSpecialFloats,
5045       unsigned int precision,
5046       PrecisionType precisionType);
5047   int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
5048 private:
5049   void writeValue(Value const& value);
5050   void writeArrayValue(Value const& value);
5051   bool isMultilineArray(Value const& value);
5052   void pushValue(JSONCPP_STRING const& value);
5053   void writeIndent();
5054   void writeWithIndent(JSONCPP_STRING const& value);
5055   void indent();
5056   void unindent();
5057   void writeCommentBeforeValue(Value const& root);
5058   void writeCommentAfterValueOnSameLine(Value const& root);
5059   static bool hasCommentForValue(const Value& value);
5060 
5061   typedef std::vector<JSONCPP_STRING> ChildValues;
5062 
5063   ChildValues childValues_;
5064   JSONCPP_STRING indentString_;
5065   unsigned int rightMargin_;
5066   JSONCPP_STRING indentation_;
5067   CommentStyle::Enum cs_;
5068   JSONCPP_STRING colonSymbol_;
5069   JSONCPP_STRING nullSymbol_;
5070   JSONCPP_STRING endingLineFeedSymbol_;
5071   bool addChildValues_ : 1;
5072   bool indented_ : 1;
5073   bool useSpecialFloats_ : 1;
5074   unsigned int precision_;
5075   PrecisionType precisionType_;
5076 };
5077 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
5078       JSONCPP_STRING const& indentation,
5079       CommentStyle::Enum cs,
5080       JSONCPP_STRING const& colonSymbol,
5081       JSONCPP_STRING const& nullSymbol,
5082       JSONCPP_STRING const& endingLineFeedSymbol,
5083       bool useSpecialFloats,
5084       unsigned int precision,
5085       PrecisionType precisionType)
5086   : rightMargin_(74)
5087   , indentation_(indentation)
5088   , cs_(cs)
5089   , colonSymbol_(colonSymbol)
5090   , nullSymbol_(nullSymbol)
5091   , endingLineFeedSymbol_(endingLineFeedSymbol)
5092   , addChildValues_(false)
5093   , indented_(false)
5094   , useSpecialFloats_(useSpecialFloats)
5095   , precision_(precision)
5096   , precisionType_(precisionType)
5097 {
5098 }
5099 int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
5100 {
5101   sout_ = sout;
5102   addChildValues_ = false;
5103   indented_ = true;
5104   indentString_.clear();
5105   writeCommentBeforeValue(root);
5106   if (!indented_) writeIndent();
5107   indented_ = true;
5108   writeValue(root);
5109   writeCommentAfterValueOnSameLine(root);
5110   *sout_ << endingLineFeedSymbol_;
5111   sout_ = NULL;
5112   return 0;
5113 }
5114 void BuiltStyledStreamWriter::writeValue(Value const& value) {
5115   switch (value.type()) {
5116   case nullValue:
5117     pushValue(nullSymbol_);
5118     break;
5119   case intValue:
5120     pushValue(valueToString(value.asLargestInt()));
5121     break;
5122   case uintValue:
5123     pushValue(valueToString(value.asLargestUInt()));
5124     break;
5125   case realValue:
5126     pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_, precisionType_));
5127     break;
5128   case stringValue:
5129   {
5130     // Is NULL is possible for value.string_? No.
5131     char const* str;
5132     char const* end;
5133     bool ok = value.getString(&str, &end);
5134     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
5135     else pushValue("");
5136     break;
5137   }
5138   case booleanValue:
5139     pushValue(valueToString(value.asBool()));
5140     break;
5141   case arrayValue:
5142     writeArrayValue(value);
5143     break;
5144   case objectValue: {
5145     Value::Members members(value.getMemberNames());
5146     if (members.empty())
5147       pushValue("{}");
5148     else {
5149       writeWithIndent("{");
5150       indent();
5151       Value::Members::iterator it = members.begin();
5152       for (;;) {
5153         JSONCPP_STRING const& name = *it;
5154         Value const& childValue = value[name];
5155         writeCommentBeforeValue(childValue);
5156         writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
5157         *sout_ << colonSymbol_;
5158         writeValue(childValue);
5159         if (++it == members.end()) {
5160           writeCommentAfterValueOnSameLine(childValue);
5161           break;
5162         }
5163         *sout_ << ",";
5164         writeCommentAfterValueOnSameLine(childValue);
5165       }
5166       unindent();
5167       writeWithIndent("}");
5168     }
5169   } break;
5170   }
5171 }
5172 
5173 void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
5174   unsigned size = value.size();
5175   if (size == 0)
5176     pushValue("[]");
5177   else {
5178     bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
5179     if (isMultiLine) {
5180       writeWithIndent("[");
5181       indent();
5182       bool hasChildValue = !childValues_.empty();
5183       unsigned index = 0;
5184       for (;;) {
5185         Value const& childValue = value[index];
5186         writeCommentBeforeValue(childValue);
5187         if (hasChildValue)
5188           writeWithIndent(childValues_[index]);
5189         else {
5190           if (!indented_) writeIndent();
5191           indented_ = true;
5192           writeValue(childValue);
5193           indented_ = false;
5194         }
5195         if (++index == size) {
5196           writeCommentAfterValueOnSameLine(childValue);
5197           break;
5198         }
5199         *sout_ << ",";
5200         writeCommentAfterValueOnSameLine(childValue);
5201       }
5202       unindent();
5203       writeWithIndent("]");
5204     } else // output on a single line
5205     {
5206       assert(childValues_.size() == size);
5207       *sout_ << "[";
5208       if (!indentation_.empty()) *sout_ << " ";
5209       for (unsigned index = 0; index < size; ++index) {
5210         if (index > 0)
5211           *sout_ << ((!indentation_.empty()) ? ", " : ",");
5212         *sout_ << childValues_[index];
5213       }
5214       if (!indentation_.empty()) *sout_ << " ";
5215       *sout_ << "]";
5216     }
5217   }
5218 }
5219 
5220 bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
5221   ArrayIndex const size = value.size();
5222   bool isMultiLine = size * 3 >= rightMargin_;
5223   childValues_.clear();
5224   for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
5225     Value const& childValue = value[index];
5226     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
5227                         childValue.size() > 0);
5228   }
5229   if (!isMultiLine) // check if line length > max line length
5230   {
5231     childValues_.reserve(size);
5232     addChildValues_ = true;
5233     ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
5234     for (ArrayIndex index = 0; index < size; ++index) {
5235       if (hasCommentForValue(value[index])) {
5236         isMultiLine = true;
5237       }
5238       writeValue(value[index]);
5239       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
5240     }
5241     addChildValues_ = false;
5242     isMultiLine = isMultiLine || lineLength >= rightMargin_;
5243   }
5244   return isMultiLine;
5245 }
5246 
5247 void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
5248   if (addChildValues_)
5249     childValues_.push_back(value);
5250   else
5251     *sout_ << value;
5252 }
5253 
5254 void BuiltStyledStreamWriter::writeIndent() {
5255   // blep intended this to look at the so-far-written string
5256   // to determine whether we are already indented, but
5257   // with a stream we cannot do that. So we rely on some saved state.
5258   // The caller checks indented_.
5259 
5260   if (!indentation_.empty()) {
5261     // In this case, drop newlines too.
5262     *sout_ << '\n' << indentString_;
5263   }
5264 }
5265 
5266 void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
5267   if (!indented_) writeIndent();
5268   *sout_ << value;
5269   indented_ = false;
5270 }
5271 
5272 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
5273 
5274 void BuiltStyledStreamWriter::unindent() {
5275   assert(indentString_.size() >= indentation_.size());
5276   indentString_.resize(indentString_.size() - indentation_.size());
5277 }
5278 
5279 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
5280   if (cs_ == CommentStyle::None) return;
5281   if (!root.hasComment(commentBefore))
5282     return;
5283 
5284   if (!indented_) writeIndent();
5285   const JSONCPP_STRING& comment = root.getComment(commentBefore);
5286   JSONCPP_STRING::const_iterator iter = comment.begin();
5287   while (iter != comment.end()) {
5288     *sout_ << *iter;
5289     if (*iter == '\n' &&
5290        ((iter+1) != comment.end() && *(iter + 1) == '/'))
5291       // writeIndent();  // would write extra newline
5292       *sout_ << indentString_;
5293     ++iter;
5294   }
5295   indented_ = false;
5296 }
5297 
5298 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
5299   if (cs_ == CommentStyle::None) return;
5300   if (root.hasComment(commentAfterOnSameLine))
5301     *sout_ << " " + root.getComment(commentAfterOnSameLine);
5302 
5303   if (root.hasComment(commentAfter)) {
5304     writeIndent();
5305     *sout_ << root.getComment(commentAfter);
5306   }
5307 }
5308 
5309 // static
5310 bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
5311   return value.hasComment(commentBefore) ||
5312          value.hasComment(commentAfterOnSameLine) ||
5313          value.hasComment(commentAfter);
5314 }
5315 
5316 ///////////////
5317 // StreamWriter
5318 
5319 StreamWriter::StreamWriter()
5320     : sout_(NULL)
5321 {
5322 }
5323 StreamWriter::~StreamWriter()
5324 {
5325 }
5326 StreamWriter::Factory::~Factory()
5327 {}
5328 StreamWriterBuilder::StreamWriterBuilder()
5329 {
5330   setDefaults(&settings_);
5331 }
5332 StreamWriterBuilder::~StreamWriterBuilder()
5333 {}
5334 StreamWriter* StreamWriterBuilder::newStreamWriter() const
5335 {
5336   JSONCPP_STRING indentation = settings_["indentation"].asString();
5337   JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
5338   JSONCPP_STRING pt_str = settings_["precisionType"].asString();
5339   bool eyc = settings_["enableYAMLCompatibility"].asBool();
5340   bool dnp = settings_["dropNullPlaceholders"].asBool();
5341   bool usf = settings_["useSpecialFloats"].asBool(); 
5342   unsigned int pre = settings_["precision"].asUInt();
5343   CommentStyle::Enum cs = CommentStyle::All;
5344   if (cs_str == "All") {
5345     cs = CommentStyle::All;
5346   } else if (cs_str == "None") {
5347     cs = CommentStyle::None;
5348   } else {
5349     throwRuntimeError("commentStyle must be 'All' or 'None'");
5350   }
5351   PrecisionType precisionType(significantDigits);
5352   if (pt_str == "significant") {
5353     precisionType = PrecisionType::significantDigits;
5354   } else if (pt_str == "decimal") {
5355     precisionType = PrecisionType::decimalPlaces;
5356   } else {
5357     throwRuntimeError("precisionType must be 'significant' or 'decimal'");
5358   }
5359   JSONCPP_STRING colonSymbol = " : ";
5360   if (eyc) {
5361     colonSymbol = ": ";
5362   } else if (indentation.empty()) {
5363     colonSymbol = ":";
5364   }
5365   JSONCPP_STRING nullSymbol = "null";
5366   if (dnp) {
5367     nullSymbol.clear();
5368   }
5369   if (pre > 17) pre = 17;
5370   JSONCPP_STRING endingLineFeedSymbol;
5371   return new BuiltStyledStreamWriter(
5372       indentation, cs,
5373       colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre, precisionType);
5374 }
5375 static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
5376 {
5377   valid_keys->clear();
5378   valid_keys->insert("indentation");
5379   valid_keys->insert("commentStyle");
5380   valid_keys->insert("enableYAMLCompatibility");
5381   valid_keys->insert("dropNullPlaceholders");
5382   valid_keys->insert("useSpecialFloats");
5383   valid_keys->insert("precision");
5384   valid_keys->insert("precisionType");
5385 }
5386 bool StreamWriterBuilder::validate(Json::Value* invalid) const
5387 {
5388   Json::Value my_invalid;
5389   if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
5390   Json::Value& inv = *invalid;
5391   std::set<JSONCPP_STRING> valid_keys;
5392   getValidWriterKeys(&valid_keys);
5393   Value::Members keys = settings_.getMemberNames();
5394   size_t n = keys.size();
5395   for (size_t i = 0; i < n; ++i) {
5396     JSONCPP_STRING const& key = keys[i];
5397     if (valid_keys.find(key) == valid_keys.end()) {
5398       inv[key] = settings_[key];
5399     }
5400   }
5401   return 0u == inv.size();
5402 }
5403 Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
5404 {
5405   return settings_[key];
5406 }
5407 // static
5408 void StreamWriterBuilder::setDefaults(Json::Value* settings)
5409 {
5410   //! [StreamWriterBuilderDefaults]
5411   (*settings)["commentStyle"] = "All";
5412   (*settings)["indentation"] = "\t";
5413   (*settings)["enableYAMLCompatibility"] = false;
5414   (*settings)["dropNullPlaceholders"] = false;
5415   (*settings)["useSpecialFloats"] = false;
5416   (*settings)["precision"] = 17;
5417   (*settings)["precisionType"] = "significant";
5418   //! [StreamWriterBuilderDefaults]
5419 }
5420 
5421 JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
5422   JSONCPP_OSTRINGSTREAM sout;
5423   StreamWriterPtr const writer(builder.newStreamWriter());
5424   writer->write(root, &sout);
5425   return sout.str();
5426 }
5427 
5428 JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
5429   StreamWriterBuilder builder;
5430   StreamWriterPtr const writer(builder.newStreamWriter());
5431   writer->write(root, &sout);
5432   return sout;
5433 }
5434 
5435 } // namespace Json
5436 
5437 // //////////////////////////////////////////////////////////////////////
5438 // End of content of file: src/lib_json/json_writer.cpp
5439 // //////////////////////////////////////////////////////////////////////
5440 
5441 
5442 
5443 
5444