• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2 /// It is intended to be used with #include "json/json.h"
3 
4 // //////////////////////////////////////////////////////////////////////
5 // Beginning of content of file: LICENSE
6 // //////////////////////////////////////////////////////////////////////
7 
8 /*
9 The JsonCpp library's source code, including accompanying documentation,
10 tests and demonstration applications, are licensed under the following
11 conditions...
12 
13 The author (Baptiste Lepilleur) explicitly disclaims copyright in all
14 jurisdictions which recognize such a disclaimer. In such jurisdictions,
15 this software is released into the Public Domain.
16 
17 In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
18 2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
19 released under the terms of the MIT License (see below).
20 
21 In jurisdictions which recognize Public Domain property, the user of this
22 software may choose to accept it either as 1) Public Domain, 2) under the
23 conditions of the MIT License (see below), or 3) under the terms of dual
24 Public Domain/MIT License conditions described here, as they choose.
25 
26 The MIT License is about as close to Public Domain as a license can get, and is
27 described in clear, concise terms at:
28 
29    http://en.wikipedia.org/wiki/MIT_License
30 
31 The full text of the MIT License follows:
32 
33 ========================================================================
34 Copyright (c) 2007-2010 Baptiste Lepilleur
35 
36 Permission is hereby granted, free of charge, to any person
37 obtaining a copy of this software and associated documentation
38 files (the "Software"), to deal in the Software without
39 restriction, including without limitation the rights to use, copy,
40 modify, merge, publish, distribute, sublicense, and/or sell copies
41 of the Software, and to permit persons to whom the Software is
42 furnished to do so, subject to the following conditions:
43 
44 The above copyright notice and this permission notice shall be
45 included in all copies or substantial portions of the Software.
46 
47 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
48 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
49 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
50 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
51 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
52 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
53 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
54 SOFTWARE.
55 ========================================================================
56 (END LICENSE TEXT)
57 
58 The MIT license is compatible with both the GPL and commercial
59 software, affording one all of the rights of Public Domain with the
60 minor nuisance of being required to keep the above copyright notice
61 and license text in the source code. Note also that by accepting the
62 Public Domain "license" you can re-license your copy using whatever
63 license you like.
64 
65 */
66 
67 // //////////////////////////////////////////////////////////////////////
68 // End of content of file: LICENSE
69 // //////////////////////////////////////////////////////////////////////
70 
71 
72 
73 
74 
75 
76 #include "third_party/jsoncpp/json.h"
77 
78 #ifndef JSON_IS_AMALGAMATION
79 #error "Compile with -I PATH_TO_JSON_DIRECTORY"
80 #endif
81 
82 
83 // //////////////////////////////////////////////////////////////////////
84 // Beginning of content of file: src/lib_json/json_tool.h
85 // //////////////////////////////////////////////////////////////////////
86 
87 // Copyright 2007-2010 Baptiste Lepilleur
88 // Distributed under MIT license, or public domain if desired and
89 // recognized in your jurisdiction.
90 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
91 
92 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
93 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
94 
95 /* This header provides common string manipulation support, such as UTF-8,
96  * portable conversion from/to string...
97  *
98  * It is an internal header that must not be exposed.
99  */
100 
101 namespace Json {
102 
103 /// Converts a unicode code-point to UTF-8.
codePointToUTF8(unsigned int cp)104 static inline std::string codePointToUTF8(unsigned int cp) {
105   std::string result;
106 
107   // based on description from http://en.wikipedia.org/wiki/UTF-8
108 
109   if (cp <= 0x7f) {
110     result.resize(1);
111     result[0] = static_cast<char>(cp);
112   } else if (cp <= 0x7FF) {
113     result.resize(2);
114     result[1] = static_cast<char>(0x80 | (0x3f & cp));
115     result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
116   } else if (cp <= 0xFFFF) {
117     result.resize(3);
118     result[2] = static_cast<char>(0x80 | (0x3f & cp));
119     result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
120     result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
121   } else if (cp <= 0x10FFFF) {
122     result.resize(4);
123     result[3] = static_cast<char>(0x80 | (0x3f & cp));
124     result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
125     result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
126     result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
127   }
128 
129   return result;
130 }
131 
132 /// Returns true if ch is a control character (in range [1,31]).
isControlCharacter(char ch)133 static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
134 
135 enum {
136   /// Constant that specify the size of the buffer that must be passed to
137   /// uintToString.
138   uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
139 };
140 
141 // Defines a char buffer for use with uintToString().
142 typedef char UIntToStringBuffer[uintToStringBufferSize];
143 
144 /** Converts an unsigned integer to string.
145  * @param value Unsigned interger to convert to string
146  * @param current Input/Output string buffer.
147  *        Must have at least uintToStringBufferSize chars free.
148  */
uintToString(LargestUInt value,char * & current)149 static inline void uintToString(LargestUInt value, char*& current) {
150   *--current = 0;
151   do {
152     *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
153     value /= 10;
154   } while (value != 0);
155 }
156 
157 /** Change ',' to '.' everywhere in buffer.
158  *
159  * We had a sophisticated way, but it did not work in WinCE.
160  * @see https://github.com/open-source-parsers/jsoncpp/pull/9
161  */
fixNumericLocale(char * begin,char * end)162 static inline void fixNumericLocale(char* begin, char* end) {
163   while (begin < end) {
164     if (*begin == ',') {
165       *begin = '.';
166     }
167     ++begin;
168   }
169 }
170 
171 } // namespace Json {
172 
173 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
174 
175 // //////////////////////////////////////////////////////////////////////
176 // End of content of file: src/lib_json/json_tool.h
177 // //////////////////////////////////////////////////////////////////////
178 
179 
180 
181 
182 
183 
184 // //////////////////////////////////////////////////////////////////////
185 // Beginning of content of file: src/lib_json/json_reader.cpp
186 // //////////////////////////////////////////////////////////////////////
187 
188 // Copyright 2007-2011 Baptiste Lepilleur
189 // Distributed under MIT license, or public domain if desired and
190 // recognized in your jurisdiction.
191 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
192 
193 #if !defined(JSON_IS_AMALGAMATION)
194 #include <json/assertions.h>
195 #include <json/reader.h>
196 #include <json/value.h>
197 #include "json_tool.h"
198 #endif // if !defined(JSON_IS_AMALGAMATION)
199 #include <utility>
200 #include <cstdio>
201 #include <cassert>
202 #include <cstring>
203 #include <istream>
204 #include <sstream>
205 #include <memory>
206 #include <set>
207 #include <limits>
208 
209 #if defined(_MSC_VER)
210 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
211 #define snprintf sprintf_s
212 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
213 #define snprintf std::snprintf
214 #else
215 #define snprintf _snprintf
216 #endif
217 #elif defined(__ANDROID__) || defined(__QNXNTO__)
218 #define snprintf snprintf
219 #elif __cplusplus >= 201103L
220 #define snprintf std::snprintf
221 #endif
222 
223 #if defined(__QNXNTO__)
224 #define sscanf std::sscanf
225 #endif
226 
227 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
228 // Disable warning about strdup being deprecated.
229 #pragma warning(disable : 4996)
230 #endif
231 
232 static int const stackLimit_g = 1000;
233 static int       stackDepth_g = 0;  // see readValue()
234 
235 namespace Json {
236 
237 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
238 typedef std::unique_ptr<CharReader> CharReaderPtr;
239 #else
240 typedef std::auto_ptr<CharReader>   CharReaderPtr;
241 #endif
242 
243 // Implementation of class Features
244 // ////////////////////////////////
245 
Features()246 Features::Features()
247     : allowComments_(true), strictRoot_(false),
248       allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
249 
all()250 Features Features::all() { return Features(); }
251 
strictMode()252 Features Features::strictMode() {
253   Features features;
254   features.allowComments_ = false;
255   features.strictRoot_ = true;
256   features.allowDroppedNullPlaceholders_ = false;
257   features.allowNumericKeys_ = false;
258   return features;
259 }
260 
261 // Implementation of class Reader
262 // ////////////////////////////////
263 
containsNewLine(Reader::Location begin,Reader::Location end)264 static bool containsNewLine(Reader::Location begin, Reader::Location end) {
265   for (; begin < end; ++begin)
266     if (*begin == '\n' || *begin == '\r')
267       return true;
268   return false;
269 }
270 
271 // Class Reader
272 // //////////////////////////////////////////////////////////////////
273 
Reader()274 Reader::Reader()
275     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
276       lastValue_(), commentsBefore_(), features_(Features::all()),
277       collectComments_() {}
278 
Reader(const Features & features)279 Reader::Reader(const Features& features)
280     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
281       lastValue_(), commentsBefore_(), features_(features), collectComments_() {
282 }
283 
284 bool
parse(const std::string & document,Value & root,bool collectComments)285 Reader::parse(const std::string& document, Value& root, bool collectComments) {
286   document_ = document;
287   const char* begin = document_.c_str();
288   const char* end = begin + document_.length();
289   return parse(begin, end, root, collectComments);
290 }
291 
parse(std::istream & sin,Value & root,bool collectComments)292 bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
293   // std::istream_iterator<char> begin(sin);
294   // std::istream_iterator<char> end;
295   // Those would allow streamed input from a file, if parse() were a
296   // template function.
297 
298   // Since std::string is reference-counted, this at least does not
299   // create an extra copy.
300   std::string doc;
301   std::getline(sin, doc, (char)EOF);
302   return parse(doc, root, collectComments);
303 }
304 
parse(const char * beginDoc,const char * endDoc,Value & root,bool collectComments)305 bool Reader::parse(const char* beginDoc,
306                    const char* endDoc,
307                    Value& root,
308                    bool collectComments) {
309   if (!features_.allowComments_) {
310     collectComments = false;
311   }
312 
313   begin_ = beginDoc;
314   end_ = endDoc;
315   collectComments_ = collectComments;
316   current_ = begin_;
317   lastValueEnd_ = 0;
318   lastValue_ = 0;
319   commentsBefore_ = "";
320   errors_.clear();
321   while (!nodes_.empty())
322     nodes_.pop();
323   nodes_.push(&root);
324 
325   stackDepth_g = 0;  // Yes, this is bad coding, but options are limited.
326   bool successful = readValue();
327   Token token;
328   skipCommentTokens(token);
329   if (collectComments_ && !commentsBefore_.empty())
330     root.setComment(commentsBefore_, commentAfter);
331   if (features_.strictRoot_) {
332     if (!root.isArray() && !root.isObject()) {
333       // Set error location to start of doc, ideally should be first token found
334       // in doc
335       token.type_ = tokenError;
336       token.start_ = beginDoc;
337       token.end_ = endDoc;
338       addError(
339           "A valid JSON document must be either an array or an object value.",
340           token);
341       return false;
342     }
343   }
344   return successful;
345 }
346 
readValue()347 bool Reader::readValue() {
348   // This is a non-reentrant way to support a stackLimit. Terrible!
349   // But this deprecated class has a security problem: Bad input can
350   // cause a seg-fault. This seems like a fair, binary-compatible way
351   // to prevent the problem.
352   if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
353   ++stackDepth_g;
354 
355   Token token;
356   skipCommentTokens(token);
357   bool successful = true;
358 
359   if (collectComments_ && !commentsBefore_.empty()) {
360     currentValue().setComment(commentsBefore_, commentBefore);
361     commentsBefore_ = "";
362   }
363 
364   switch (token.type_) {
365   case tokenObjectBegin:
366     successful = readObject(token);
367     currentValue().setOffsetLimit(current_ - begin_);
368     break;
369   case tokenArrayBegin:
370     successful = readArray(token);
371     currentValue().setOffsetLimit(current_ - begin_);
372     break;
373   case tokenNumber:
374     successful = decodeNumber(token);
375     break;
376   case tokenString:
377     successful = decodeString(token);
378     break;
379   case tokenTrue:
380     {
381     Value v(true);
382     currentValue().swapPayload(v);
383     currentValue().setOffsetStart(token.start_ - begin_);
384     currentValue().setOffsetLimit(token.end_ - begin_);
385     }
386     break;
387   case tokenFalse:
388     {
389     Value v(false);
390     currentValue().swapPayload(v);
391     currentValue().setOffsetStart(token.start_ - begin_);
392     currentValue().setOffsetLimit(token.end_ - begin_);
393     }
394     break;
395   case tokenNull:
396     {
397     Value v;
398     currentValue().swapPayload(v);
399     currentValue().setOffsetStart(token.start_ - begin_);
400     currentValue().setOffsetLimit(token.end_ - begin_);
401     }
402     break;
403   case tokenArraySeparator:
404   case tokenObjectEnd:
405   case tokenArrayEnd:
406     if (features_.allowDroppedNullPlaceholders_) {
407       // "Un-read" the current token and mark the current value as a null
408       // token.
409       current_--;
410       Value v;
411       currentValue().swapPayload(v);
412       currentValue().setOffsetStart(current_ - begin_ - 1);
413       currentValue().setOffsetLimit(current_ - begin_);
414       break;
415     } // Else, fall through...
416   default:
417     currentValue().setOffsetStart(token.start_ - begin_);
418     currentValue().setOffsetLimit(token.end_ - begin_);
419     return addError("Syntax error: value, object or array expected.", token);
420   }
421 
422   if (collectComments_) {
423     lastValueEnd_ = current_;
424     lastValue_ = &currentValue();
425   }
426 
427   --stackDepth_g;
428   return successful;
429 }
430 
skipCommentTokens(Token & token)431 void Reader::skipCommentTokens(Token& token) {
432   if (features_.allowComments_) {
433     do {
434       readToken(token);
435     } while (token.type_ == tokenComment);
436   } else {
437     readToken(token);
438   }
439 }
440 
readToken(Token & token)441 bool Reader::readToken(Token& token) {
442   skipSpaces();
443   token.start_ = current_;
444   Char c = getNextChar();
445   bool ok = true;
446   switch (c) {
447   case '{':
448     token.type_ = tokenObjectBegin;
449     break;
450   case '}':
451     token.type_ = tokenObjectEnd;
452     break;
453   case '[':
454     token.type_ = tokenArrayBegin;
455     break;
456   case ']':
457     token.type_ = tokenArrayEnd;
458     break;
459   case '"':
460     token.type_ = tokenString;
461     ok = readString();
462     break;
463   case '/':
464     token.type_ = tokenComment;
465     ok = readComment();
466     break;
467   case '0':
468   case '1':
469   case '2':
470   case '3':
471   case '4':
472   case '5':
473   case '6':
474   case '7':
475   case '8':
476   case '9':
477   case '-':
478     token.type_ = tokenNumber;
479     readNumber();
480     break;
481   case 't':
482     token.type_ = tokenTrue;
483     ok = match("rue", 3);
484     break;
485   case 'f':
486     token.type_ = tokenFalse;
487     ok = match("alse", 4);
488     break;
489   case 'n':
490     token.type_ = tokenNull;
491     ok = match("ull", 3);
492     break;
493   case ',':
494     token.type_ = tokenArraySeparator;
495     break;
496   case ':':
497     token.type_ = tokenMemberSeparator;
498     break;
499   case 0:
500     token.type_ = tokenEndOfStream;
501     break;
502   default:
503     ok = false;
504     break;
505   }
506   if (!ok)
507     token.type_ = tokenError;
508   token.end_ = current_;
509   return true;
510 }
511 
skipSpaces()512 void Reader::skipSpaces() {
513   while (current_ != end_) {
514     Char c = *current_;
515     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
516       ++current_;
517     else
518       break;
519   }
520 }
521 
match(Location pattern,int patternLength)522 bool Reader::match(Location pattern, int patternLength) {
523   if (end_ - current_ < patternLength)
524     return false;
525   int index = patternLength;
526   while (index--)
527     if (current_[index] != pattern[index])
528       return false;
529   current_ += patternLength;
530   return true;
531 }
532 
readComment()533 bool Reader::readComment() {
534   Location commentBegin = current_ - 1;
535   Char c = getNextChar();
536   bool successful = false;
537   if (c == '*')
538     successful = readCStyleComment();
539   else if (c == '/')
540     successful = readCppStyleComment();
541   if (!successful)
542     return false;
543 
544   if (collectComments_) {
545     CommentPlacement placement = commentBefore;
546     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
547       if (c != '*' || !containsNewLine(commentBegin, current_))
548         placement = commentAfterOnSameLine;
549     }
550 
551     addComment(commentBegin, current_, placement);
552   }
553   return true;
554 }
555 
normalizeEOL(Reader::Location begin,Reader::Location end)556 static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
557   std::string normalized;
558   normalized.reserve(end - begin);
559   Reader::Location current = begin;
560   while (current != end) {
561     char c = *current++;
562     if (c == '\r') {
563       if (current != end && *current == '\n')
564          // convert dos EOL
565          ++current;
566       // convert Mac EOL
567       normalized += '\n';
568     } else {
569       normalized += c;
570     }
571   }
572   return normalized;
573 }
574 
575 void
addComment(Location begin,Location end,CommentPlacement placement)576 Reader::addComment(Location begin, Location end, CommentPlacement placement) {
577   assert(collectComments_);
578   const std::string& normalized = normalizeEOL(begin, end);
579   if (placement == commentAfterOnSameLine) {
580     assert(lastValue_ != 0);
581     lastValue_->setComment(normalized, placement);
582   } else {
583     commentsBefore_ += normalized;
584   }
585 }
586 
readCStyleComment()587 bool Reader::readCStyleComment() {
588   while (current_ != end_) {
589     Char c = getNextChar();
590     if (c == '*' && *current_ == '/')
591       break;
592   }
593   return getNextChar() == '/';
594 }
595 
readCppStyleComment()596 bool Reader::readCppStyleComment() {
597   while (current_ != end_) {
598     Char c = getNextChar();
599     if (c == '\n')
600       break;
601     if (c == '\r') {
602       // Consume DOS EOL. It will be normalized in addComment.
603       if (current_ != end_ && *current_ == '\n')
604         getNextChar();
605       // Break on Moc OS 9 EOL.
606       break;
607     }
608   }
609   return true;
610 }
611 
readNumber()612 void Reader::readNumber() {
613   const char *p = current_;
614   char c = '0'; // stopgap for already consumed character
615   // integral part
616   while (c >= '0' && c <= '9')
617     c = (current_ = p) < end_ ? *p++ : 0;
618   // fractional part
619   if (c == '.') {
620     c = (current_ = p) < end_ ? *p++ : 0;
621     while (c >= '0' && c <= '9')
622       c = (current_ = p) < end_ ? *p++ : 0;
623   }
624   // exponential part
625   if (c == 'e' || c == 'E') {
626     c = (current_ = p) < end_ ? *p++ : 0;
627     if (c == '+' || c == '-')
628       c = (current_ = p) < end_ ? *p++ : 0;
629     while (c >= '0' && c <= '9')
630       c = (current_ = p) < end_ ? *p++ : 0;
631   }
632 }
633 
readString()634 bool Reader::readString() {
635   Char c = 0;
636   while (current_ != end_) {
637     c = getNextChar();
638     if (c == '\\')
639       getNextChar();
640     else if (c == '"')
641       break;
642   }
643   return c == '"';
644 }
645 
readObject(Token & tokenStart)646 bool Reader::readObject(Token& tokenStart) {
647   Token tokenName;
648   std::string name;
649   Value init(objectValue);
650   currentValue().swapPayload(init);
651   currentValue().setOffsetStart(tokenStart.start_ - begin_);
652   while (readToken(tokenName)) {
653     bool initialTokenOk = true;
654     while (tokenName.type_ == tokenComment && initialTokenOk)
655       initialTokenOk = readToken(tokenName);
656     if (!initialTokenOk)
657       break;
658     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
659       return true;
660     name = "";
661     if (tokenName.type_ == tokenString) {
662       if (!decodeString(tokenName, name))
663         return recoverFromError(tokenObjectEnd);
664     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
665       Value numberName;
666       if (!decodeNumber(tokenName, numberName))
667         return recoverFromError(tokenObjectEnd);
668       name = numberName.asString();
669     } else {
670       break;
671     }
672 
673     Token colon;
674     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
675       return addErrorAndRecover(
676           "Missing ':' after object member name", colon, tokenObjectEnd);
677     }
678     Value& value = currentValue()[name];
679     nodes_.push(&value);
680     bool ok = readValue();
681     nodes_.pop();
682     if (!ok) // error already set
683       return recoverFromError(tokenObjectEnd);
684 
685     Token comma;
686     if (!readToken(comma) ||
687         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
688          comma.type_ != tokenComment)) {
689       return addErrorAndRecover(
690           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
691     }
692     bool finalizeTokenOk = true;
693     while (comma.type_ == tokenComment && finalizeTokenOk)
694       finalizeTokenOk = readToken(comma);
695     if (comma.type_ == tokenObjectEnd)
696       return true;
697   }
698   return addErrorAndRecover(
699       "Missing '}' or object member name", tokenName, tokenObjectEnd);
700 }
701 
readArray(Token & tokenStart)702 bool Reader::readArray(Token& tokenStart) {
703   Value init(arrayValue);
704   currentValue().swapPayload(init);
705   currentValue().setOffsetStart(tokenStart.start_ - begin_);
706   skipSpaces();
707   if (*current_ == ']') // empty array
708   {
709     Token endArray;
710     readToken(endArray);
711     return true;
712   }
713   int index = 0;
714   for (;;) {
715     Value& value = currentValue()[index++];
716     nodes_.push(&value);
717     bool ok = readValue();
718     nodes_.pop();
719     if (!ok) // error already set
720       return recoverFromError(tokenArrayEnd);
721 
722     Token token;
723     // Accept Comment after last item in the array.
724     ok = readToken(token);
725     while (token.type_ == tokenComment && ok) {
726       ok = readToken(token);
727     }
728     bool badTokenType =
729         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
730     if (!ok || badTokenType) {
731       return addErrorAndRecover(
732           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
733     }
734     if (token.type_ == tokenArrayEnd)
735       break;
736   }
737   return true;
738 }
739 
decodeNumber(Token & token)740 bool Reader::decodeNumber(Token& token) {
741   Value decoded;
742   if (!decodeNumber(token, decoded))
743     return false;
744   currentValue().swapPayload(decoded);
745   currentValue().setOffsetStart(token.start_ - begin_);
746   currentValue().setOffsetLimit(token.end_ - begin_);
747   return true;
748 }
749 
decodeNumber(Token & token,Value & decoded)750 bool Reader::decodeNumber(Token& token, Value& decoded) {
751   // Attempts to parse the number as an integer. If the number is
752   // larger than the maximum supported value of an integer then
753   // we decode the number as a double.
754   Location current = token.start_;
755   bool isNegative = *current == '-';
756   if (isNegative)
757     ++current;
758   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
759   Value::LargestUInt maxIntegerValue =
760       isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
761                  : Value::maxLargestUInt;
762   Value::LargestUInt threshold = maxIntegerValue / 10;
763   Value::LargestUInt value = 0;
764   while (current < token.end_) {
765     Char c = *current++;
766     if (c < '0' || c > '9')
767       return decodeDouble(token, decoded);
768     Value::UInt digit(c - '0');
769     if (value >= threshold) {
770       // We've hit or exceeded the max value divided by 10 (rounded down). If
771       // a) we've only just touched the limit, b) this is the last digit, and
772       // c) it's small enough to fit in that rounding delta, we're okay.
773       // Otherwise treat this number as a double to avoid overflow.
774       if (value > threshold || current != token.end_ ||
775           digit > maxIntegerValue % 10) {
776         return decodeDouble(token, decoded);
777       }
778     }
779     value = value * 10 + digit;
780   }
781   if (isNegative && value == maxIntegerValue)
782     decoded = Value::minLargestInt;
783   else if (isNegative)
784     decoded = -Value::LargestInt(value);
785   else if (value <= Value::LargestUInt(Value::maxInt))
786     decoded = Value::LargestInt(value);
787   else
788     decoded = value;
789   return true;
790 }
791 
decodeDouble(Token & token)792 bool Reader::decodeDouble(Token& token) {
793   Value decoded;
794   if (!decodeDouble(token, decoded))
795     return false;
796   currentValue().swapPayload(decoded);
797   currentValue().setOffsetStart(token.start_ - begin_);
798   currentValue().setOffsetLimit(token.end_ - begin_);
799   return true;
800 }
801 
decodeDouble(Token & token,Value & decoded)802 bool Reader::decodeDouble(Token& token, Value& decoded) {
803   double value = 0;
804   std::string buffer(token.start_, token.end_);
805   std::istringstream is(buffer);
806   if (!(is >> value))
807     return addError("'" + std::string(token.start_, token.end_) +
808                         "' is not a number.",
809                     token);
810   decoded = value;
811   return true;
812 }
813 
decodeString(Token & token)814 bool Reader::decodeString(Token& token) {
815   std::string decoded_string;
816   if (!decodeString(token, decoded_string))
817     return false;
818   Value decoded(decoded_string);
819   currentValue().swapPayload(decoded);
820   currentValue().setOffsetStart(token.start_ - begin_);
821   currentValue().setOffsetLimit(token.end_ - begin_);
822   return true;
823 }
824 
decodeString(Token & token,std::string & decoded)825 bool Reader::decodeString(Token& token, std::string& decoded) {
826   decoded.reserve(token.end_ - token.start_ - 2);
827   Location current = token.start_ + 1; // skip '"'
828   Location end = token.end_ - 1;       // do not include '"'
829   while (current != end) {
830     Char c = *current++;
831     if (c == '"')
832       break;
833     else if (c == '\\') {
834       if (current == end)
835         return addError("Empty escape sequence in string", token, current);
836       Char escape = *current++;
837       switch (escape) {
838       case '"':
839         decoded += '"';
840         break;
841       case '/':
842         decoded += '/';
843         break;
844       case '\\':
845         decoded += '\\';
846         break;
847       case 'b':
848         decoded += '\b';
849         break;
850       case 'f':
851         decoded += '\f';
852         break;
853       case 'n':
854         decoded += '\n';
855         break;
856       case 'r':
857         decoded += '\r';
858         break;
859       case 't':
860         decoded += '\t';
861         break;
862       case 'u': {
863         unsigned int unicode;
864         if (!decodeUnicodeCodePoint(token, current, end, unicode))
865           return false;
866         decoded += codePointToUTF8(unicode);
867       } break;
868       default:
869         return addError("Bad escape sequence in string", token, current);
870       }
871     } else {
872       decoded += c;
873     }
874   }
875   return true;
876 }
877 
decodeUnicodeCodePoint(Token & token,Location & current,Location end,unsigned int & unicode)878 bool Reader::decodeUnicodeCodePoint(Token& token,
879                                     Location& current,
880                                     Location end,
881                                     unsigned int& unicode) {
882 
883   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
884     return false;
885   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
886     // surrogate pairs
887     if (end - current < 6)
888       return addError(
889           "additional six characters expected to parse unicode surrogate pair.",
890           token,
891           current);
892     unsigned int surrogatePair;
893     if (*(current++) == '\\' && *(current++) == 'u') {
894       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
895         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
896       } else
897         return false;
898     } else
899       return addError("expecting another \\u token to begin the second half of "
900                       "a unicode surrogate pair",
901                       token,
902                       current);
903   }
904   return true;
905 }
906 
decodeUnicodeEscapeSequence(Token & token,Location & current,Location end,unsigned int & unicode)907 bool Reader::decodeUnicodeEscapeSequence(Token& token,
908                                          Location& current,
909                                          Location end,
910                                          unsigned int& unicode) {
911   if (end - current < 4)
912     return addError(
913         "Bad unicode escape sequence in string: four digits expected.",
914         token,
915         current);
916   unicode = 0;
917   for (int index = 0; index < 4; ++index) {
918     Char c = *current++;
919     unicode *= 16;
920     if (c >= '0' && c <= '9')
921       unicode += c - '0';
922     else if (c >= 'a' && c <= 'f')
923       unicode += c - 'a' + 10;
924     else if (c >= 'A' && c <= 'F')
925       unicode += c - 'A' + 10;
926     else
927       return addError(
928           "Bad unicode escape sequence in string: hexadecimal digit expected.",
929           token,
930           current);
931   }
932   return true;
933 }
934 
935 bool
addError(const std::string & message,Token & token,Location extra)936 Reader::addError(const std::string& message, Token& token, Location extra) {
937   ErrorInfo info;
938   info.token_ = token;
939   info.message_ = message;
940   info.extra_ = extra;
941   errors_.push_back(info);
942   return false;
943 }
944 
recoverFromError(TokenType skipUntilToken)945 bool Reader::recoverFromError(TokenType skipUntilToken) {
946   int errorCount = int(errors_.size());
947   Token skip;
948   for (;;) {
949     if (!readToken(skip))
950       errors_.resize(errorCount); // discard errors caused by recovery
951     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
952       break;
953   }
954   errors_.resize(errorCount);
955   return false;
956 }
957 
addErrorAndRecover(const std::string & message,Token & token,TokenType skipUntilToken)958 bool Reader::addErrorAndRecover(const std::string& message,
959                                 Token& token,
960                                 TokenType skipUntilToken) {
961   addError(message, token);
962   return recoverFromError(skipUntilToken);
963 }
964 
currentValue()965 Value& Reader::currentValue() { return *(nodes_.top()); }
966 
getNextChar()967 Reader::Char Reader::getNextChar() {
968   if (current_ == end_)
969     return 0;
970   return *current_++;
971 }
972 
getLocationLineAndColumn(Location location,int & line,int & column) const973 void Reader::getLocationLineAndColumn(Location location,
974                                       int& line,
975                                       int& column) const {
976   Location current = begin_;
977   Location lastLineStart = current;
978   line = 0;
979   while (current < location && current != end_) {
980     Char c = *current++;
981     if (c == '\r') {
982       if (*current == '\n')
983         ++current;
984       lastLineStart = current;
985       ++line;
986     } else if (c == '\n') {
987       lastLineStart = current;
988       ++line;
989     }
990   }
991   // column & line start at 1
992   column = int(location - lastLineStart) + 1;
993   ++line;
994 }
995 
getLocationLineAndColumn(Location location) const996 std::string Reader::getLocationLineAndColumn(Location location) const {
997   int line, column;
998   getLocationLineAndColumn(location, line, column);
999   char buffer[18 + 16 + 16 + 1];
1000   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
1001   return buffer;
1002 }
1003 
1004 // Deprecated. Preserved for backward compatibility
getFormatedErrorMessages() const1005 std::string Reader::getFormatedErrorMessages() const {
1006   return getFormattedErrorMessages();
1007 }
1008 
getFormattedErrorMessages() const1009 std::string Reader::getFormattedErrorMessages() const {
1010   std::string formattedMessage;
1011   for (Errors::const_iterator itError = errors_.begin();
1012        itError != errors_.end();
1013        ++itError) {
1014     const ErrorInfo& error = *itError;
1015     formattedMessage +=
1016         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
1017     formattedMessage += "  " + error.message_ + "\n";
1018     if (error.extra_)
1019       formattedMessage +=
1020           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
1021   }
1022   return formattedMessage;
1023 }
1024 
getStructuredErrors() const1025 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
1026   std::vector<Reader::StructuredError> allErrors;
1027   for (Errors::const_iterator itError = errors_.begin();
1028        itError != errors_.end();
1029        ++itError) {
1030     const ErrorInfo& error = *itError;
1031     Reader::StructuredError structured;
1032     structured.offset_start = error.token_.start_ - begin_;
1033     structured.offset_limit = error.token_.end_ - begin_;
1034     structured.message = error.message_;
1035     allErrors.push_back(structured);
1036   }
1037   return allErrors;
1038 }
1039 
pushError(const Value & value,const std::string & message)1040 bool Reader::pushError(const Value& value, const std::string& message) {
1041   size_t length = end_ - begin_;
1042   if(value.getOffsetStart() > length
1043     || value.getOffsetLimit() > length)
1044     return false;
1045   Token token;
1046   token.type_ = tokenError;
1047   token.start_ = begin_ + value.getOffsetStart();
1048   token.end_ = end_ + value.getOffsetLimit();
1049   ErrorInfo info;
1050   info.token_ = token;
1051   info.message_ = message;
1052   info.extra_ = 0;
1053   errors_.push_back(info);
1054   return true;
1055 }
1056 
pushError(const Value & value,const std::string & message,const Value & extra)1057 bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
1058   size_t length = end_ - begin_;
1059   if(value.getOffsetStart() > length
1060     || value.getOffsetLimit() > length
1061     || extra.getOffsetLimit() > length)
1062     return false;
1063   Token token;
1064   token.type_ = tokenError;
1065   token.start_ = begin_ + value.getOffsetStart();
1066   token.end_ = begin_ + value.getOffsetLimit();
1067   ErrorInfo info;
1068   info.token_ = token;
1069   info.message_ = message;
1070   info.extra_ = begin_ + extra.getOffsetStart();
1071   errors_.push_back(info);
1072   return true;
1073 }
1074 
good() const1075 bool Reader::good() const {
1076   return !errors_.size();
1077 }
1078 
1079 // exact copy of Features
1080 class OurFeatures {
1081 public:
1082   static OurFeatures all();
1083   bool allowComments_;
1084   bool strictRoot_;
1085   bool allowDroppedNullPlaceholders_;
1086   bool allowNumericKeys_;
1087   bool allowSingleQuotes_;
1088   bool failIfExtra_;
1089   bool rejectDupKeys_;
1090   bool allowSpecialFloats_;
1091   int stackLimit_;
1092 };  // OurFeatures
1093 
1094 // exact copy of Implementation of class Features
1095 // ////////////////////////////////
1096 
all()1097 OurFeatures OurFeatures::all() { return OurFeatures(); }
1098 
1099 // Implementation of class Reader
1100 // ////////////////////////////////
1101 
1102 // exact copy of Reader, renamed to OurReader
1103 class OurReader {
1104 public:
1105   typedef char Char;
1106   typedef const Char* Location;
1107   struct StructuredError {
1108     size_t offset_start;
1109     size_t offset_limit;
1110     std::string message;
1111   };
1112 
1113   OurReader(OurFeatures const& features);
1114   bool parse(const char* beginDoc,
1115              const char* endDoc,
1116              Value& root,
1117              bool collectComments = true);
1118   std::string getFormattedErrorMessages() const;
1119   std::vector<StructuredError> getStructuredErrors() const;
1120   bool pushError(const Value& value, const std::string& message);
1121   bool pushError(const Value& value, const std::string& message, const Value& extra);
1122   bool good() const;
1123 
1124 private:
1125   OurReader(OurReader const&);  // no impl
1126   void operator=(OurReader const&);  // no impl
1127 
1128   enum TokenType {
1129     tokenEndOfStream = 0,
1130     tokenObjectBegin,
1131     tokenObjectEnd,
1132     tokenArrayBegin,
1133     tokenArrayEnd,
1134     tokenString,
1135     tokenNumber,
1136     tokenTrue,
1137     tokenFalse,
1138     tokenNull,
1139     tokenNaN,
1140     tokenPosInf,
1141     tokenNegInf,
1142     tokenArraySeparator,
1143     tokenMemberSeparator,
1144     tokenComment,
1145     tokenError
1146   };
1147 
1148   class Token {
1149   public:
1150     TokenType type_;
1151     Location start_;
1152     Location end_;
1153   };
1154 
1155   class ErrorInfo {
1156   public:
1157     Token token_;
1158     std::string message_;
1159     Location extra_;
1160   };
1161 
1162   typedef std::deque<ErrorInfo> Errors;
1163 
1164   bool readToken(Token& token);
1165   void skipSpaces();
1166   bool match(Location pattern, int patternLength);
1167   bool readComment();
1168   bool readCStyleComment();
1169   bool readCppStyleComment();
1170   bool readString();
1171   bool readStringSingleQuote();
1172   bool readNumber(bool checkInf);
1173   bool readValue();
1174   bool readObject(Token& token);
1175   bool readArray(Token& token);
1176   bool decodeNumber(Token& token);
1177   bool decodeNumber(Token& token, Value& decoded);
1178   bool decodeString(Token& token);
1179   bool decodeString(Token& token, std::string& decoded);
1180   bool decodeDouble(Token& token);
1181   bool decodeDouble(Token& token, Value& decoded);
1182   bool decodeUnicodeCodePoint(Token& token,
1183                               Location& current,
1184                               Location end,
1185                               unsigned int& unicode);
1186   bool decodeUnicodeEscapeSequence(Token& token,
1187                                    Location& current,
1188                                    Location end,
1189                                    unsigned int& unicode);
1190   bool addError(const std::string& message, Token& token, Location extra = 0);
1191   bool recoverFromError(TokenType skipUntilToken);
1192   bool addErrorAndRecover(const std::string& message,
1193                           Token& token,
1194                           TokenType skipUntilToken);
1195   void skipUntilSpace();
1196   Value& currentValue();
1197   Char getNextChar();
1198   void
1199   getLocationLineAndColumn(Location location, int& line, int& column) const;
1200   std::string getLocationLineAndColumn(Location location) const;
1201   void addComment(Location begin, Location end, CommentPlacement placement);
1202   void skipCommentTokens(Token& token);
1203 
1204   typedef std::stack<Value*> Nodes;
1205   Nodes nodes_;
1206   Errors errors_;
1207   std::string document_;
1208   Location begin_;
1209   Location end_;
1210   Location current_;
1211   Location lastValueEnd_;
1212   Value* lastValue_;
1213   std::string commentsBefore_;
1214   int stackDepth_;
1215 
1216   OurFeatures const features_;
1217   bool collectComments_;
1218 };  // OurReader
1219 
1220 // complete copy of Read impl, for OurReader
1221 
OurReader(OurFeatures const & features)1222 OurReader::OurReader(OurFeatures const& features)
1223     : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
1224       lastValue_(), commentsBefore_(),
1225       stackDepth_(0),
1226       features_(features), collectComments_() {
1227 }
1228 
parse(const char * beginDoc,const char * endDoc,Value & root,bool collectComments)1229 bool OurReader::parse(const char* beginDoc,
1230                    const char* endDoc,
1231                    Value& root,
1232                    bool collectComments) {
1233   if (!features_.allowComments_) {
1234     collectComments = false;
1235   }
1236 
1237   begin_ = beginDoc;
1238   end_ = endDoc;
1239   collectComments_ = collectComments;
1240   current_ = begin_;
1241   lastValueEnd_ = 0;
1242   lastValue_ = 0;
1243   commentsBefore_ = "";
1244   errors_.clear();
1245   while (!nodes_.empty())
1246     nodes_.pop();
1247   nodes_.push(&root);
1248 
1249   stackDepth_ = 0;
1250   bool successful = readValue();
1251   Token token;
1252   skipCommentTokens(token);
1253   if (features_.failIfExtra_) {
1254     if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
1255       addError("Extra non-whitespace after JSON value.", token);
1256       return false;
1257     }
1258   }
1259   if (collectComments_ && !commentsBefore_.empty())
1260     root.setComment(commentsBefore_, commentAfter);
1261   if (features_.strictRoot_) {
1262     if (!root.isArray() && !root.isObject()) {
1263       // Set error location to start of doc, ideally should be first token found
1264       // in doc
1265       token.type_ = tokenError;
1266       token.start_ = beginDoc;
1267       token.end_ = endDoc;
1268       addError(
1269           "A valid JSON document must be either an array or an object value.",
1270           token);
1271       return false;
1272     }
1273   }
1274   return successful;
1275 }
1276 
readValue()1277 bool OurReader::readValue() {
1278   if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
1279   ++stackDepth_;
1280   Token token;
1281   skipCommentTokens(token);
1282   bool successful = true;
1283 
1284   if (collectComments_ && !commentsBefore_.empty()) {
1285     currentValue().setComment(commentsBefore_, commentBefore);
1286     commentsBefore_ = "";
1287   }
1288 
1289   switch (token.type_) {
1290   case tokenObjectBegin:
1291     successful = readObject(token);
1292     currentValue().setOffsetLimit(current_ - begin_);
1293     break;
1294   case tokenArrayBegin:
1295     successful = readArray(token);
1296     currentValue().setOffsetLimit(current_ - begin_);
1297     break;
1298   case tokenNumber:
1299     successful = decodeNumber(token);
1300     break;
1301   case tokenString:
1302     successful = decodeString(token);
1303     break;
1304   case tokenTrue:
1305     {
1306     Value v(true);
1307     currentValue().swapPayload(v);
1308     currentValue().setOffsetStart(token.start_ - begin_);
1309     currentValue().setOffsetLimit(token.end_ - begin_);
1310     }
1311     break;
1312   case tokenFalse:
1313     {
1314     Value v(false);
1315     currentValue().swapPayload(v);
1316     currentValue().setOffsetStart(token.start_ - begin_);
1317     currentValue().setOffsetLimit(token.end_ - begin_);
1318     }
1319     break;
1320   case tokenNull:
1321     {
1322     Value v;
1323     currentValue().swapPayload(v);
1324     currentValue().setOffsetStart(token.start_ - begin_);
1325     currentValue().setOffsetLimit(token.end_ - begin_);
1326     }
1327     break;
1328   case tokenNaN:
1329     {
1330     Value v(std::numeric_limits<double>::quiet_NaN());
1331     currentValue().swapPayload(v);
1332     currentValue().setOffsetStart(token.start_ - begin_);
1333     currentValue().setOffsetLimit(token.end_ - begin_);
1334     }
1335     break;
1336   case tokenPosInf:
1337     {
1338     Value v(std::numeric_limits<double>::infinity());
1339     currentValue().swapPayload(v);
1340     currentValue().setOffsetStart(token.start_ - begin_);
1341     currentValue().setOffsetLimit(token.end_ - begin_);
1342     }
1343     break;
1344   case tokenNegInf:
1345     {
1346     Value v(-std::numeric_limits<double>::infinity());
1347     currentValue().swapPayload(v);
1348     currentValue().setOffsetStart(token.start_ - begin_);
1349     currentValue().setOffsetLimit(token.end_ - begin_);
1350     }
1351     break;
1352   case tokenArraySeparator:
1353   case tokenObjectEnd:
1354   case tokenArrayEnd:
1355     if (features_.allowDroppedNullPlaceholders_) {
1356       // "Un-read" the current token and mark the current value as a null
1357       // token.
1358       current_--;
1359       Value v;
1360       currentValue().swapPayload(v);
1361       currentValue().setOffsetStart(current_ - begin_ - 1);
1362       currentValue().setOffsetLimit(current_ - begin_);
1363       break;
1364     } // else, fall through ...
1365   default:
1366     currentValue().setOffsetStart(token.start_ - begin_);
1367     currentValue().setOffsetLimit(token.end_ - begin_);
1368     return addError("Syntax error: value, object or array expected.", token);
1369   }
1370 
1371   if (collectComments_) {
1372     lastValueEnd_ = current_;
1373     lastValue_ = &currentValue();
1374   }
1375 
1376   --stackDepth_;
1377   return successful;
1378 }
1379 
skipCommentTokens(Token & token)1380 void OurReader::skipCommentTokens(Token& token) {
1381   if (features_.allowComments_) {
1382     do {
1383       readToken(token);
1384     } while (token.type_ == tokenComment);
1385   } else {
1386     readToken(token);
1387   }
1388 }
1389 
readToken(Token & token)1390 bool OurReader::readToken(Token& token) {
1391   skipSpaces();
1392   token.start_ = current_;
1393   Char c = getNextChar();
1394   bool ok = true;
1395   switch (c) {
1396   case '{':
1397     token.type_ = tokenObjectBegin;
1398     break;
1399   case '}':
1400     token.type_ = tokenObjectEnd;
1401     break;
1402   case '[':
1403     token.type_ = tokenArrayBegin;
1404     break;
1405   case ']':
1406     token.type_ = tokenArrayEnd;
1407     break;
1408   case '"':
1409     token.type_ = tokenString;
1410     ok = readString();
1411     break;
1412   case '\'':
1413     if (features_.allowSingleQuotes_) {
1414     token.type_ = tokenString;
1415     ok = readStringSingleQuote();
1416     break;
1417     } // else continue
1418   case '/':
1419     token.type_ = tokenComment;
1420     ok = readComment();
1421     break;
1422   case '0':
1423   case '1':
1424   case '2':
1425   case '3':
1426   case '4':
1427   case '5':
1428   case '6':
1429   case '7':
1430   case '8':
1431   case '9':
1432     token.type_ = tokenNumber;
1433     readNumber(false);
1434     break;
1435   case '-':
1436     if (readNumber(true)) {
1437       token.type_ = tokenNumber;
1438     } else {
1439       token.type_ = tokenNegInf;
1440       ok = features_.allowSpecialFloats_ && match("nfinity", 7);
1441     }
1442     break;
1443   case 't':
1444     token.type_ = tokenTrue;
1445     ok = match("rue", 3);
1446     break;
1447   case 'f':
1448     token.type_ = tokenFalse;
1449     ok = match("alse", 4);
1450     break;
1451   case 'n':
1452     token.type_ = tokenNull;
1453     ok = match("ull", 3);
1454     break;
1455   case 'N':
1456     if (features_.allowSpecialFloats_) {
1457       token.type_ = tokenNaN;
1458       ok = match("aN", 2);
1459     } else {
1460       ok = false;
1461     }
1462     break;
1463   case 'I':
1464     if (features_.allowSpecialFloats_) {
1465       token.type_ = tokenPosInf;
1466       ok = match("nfinity", 7);
1467     } else {
1468       ok = false;
1469     }
1470     break;
1471   case ',':
1472     token.type_ = tokenArraySeparator;
1473     break;
1474   case ':':
1475     token.type_ = tokenMemberSeparator;
1476     break;
1477   case 0:
1478     token.type_ = tokenEndOfStream;
1479     break;
1480   default:
1481     ok = false;
1482     break;
1483   }
1484   if (!ok)
1485     token.type_ = tokenError;
1486   token.end_ = current_;
1487   return true;
1488 }
1489 
skipSpaces()1490 void OurReader::skipSpaces() {
1491   while (current_ != end_) {
1492     Char c = *current_;
1493     if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
1494       ++current_;
1495     else
1496       break;
1497   }
1498 }
1499 
match(Location pattern,int patternLength)1500 bool OurReader::match(Location pattern, int patternLength) {
1501   if (end_ - current_ < patternLength)
1502     return false;
1503   int index = patternLength;
1504   while (index--)
1505     if (current_[index] != pattern[index])
1506       return false;
1507   current_ += patternLength;
1508   return true;
1509 }
1510 
readComment()1511 bool OurReader::readComment() {
1512   Location commentBegin = current_ - 1;
1513   Char c = getNextChar();
1514   bool successful = false;
1515   if (c == '*')
1516     successful = readCStyleComment();
1517   else if (c == '/')
1518     successful = readCppStyleComment();
1519   if (!successful)
1520     return false;
1521 
1522   if (collectComments_) {
1523     CommentPlacement placement = commentBefore;
1524     if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
1525       if (c != '*' || !containsNewLine(commentBegin, current_))
1526         placement = commentAfterOnSameLine;
1527     }
1528 
1529     addComment(commentBegin, current_, placement);
1530   }
1531   return true;
1532 }
1533 
1534 void
addComment(Location begin,Location end,CommentPlacement placement)1535 OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
1536   assert(collectComments_);
1537   const std::string& normalized = normalizeEOL(begin, end);
1538   if (placement == commentAfterOnSameLine) {
1539     assert(lastValue_ != 0);
1540     lastValue_->setComment(normalized, placement);
1541   } else {
1542     commentsBefore_ += normalized;
1543   }
1544 }
1545 
readCStyleComment()1546 bool OurReader::readCStyleComment() {
1547   while (current_ != end_) {
1548     Char c = getNextChar();
1549     if (c == '*' && *current_ == '/')
1550       break;
1551   }
1552   return getNextChar() == '/';
1553 }
1554 
readCppStyleComment()1555 bool OurReader::readCppStyleComment() {
1556   while (current_ != end_) {
1557     Char c = getNextChar();
1558     if (c == '\n')
1559       break;
1560     if (c == '\r') {
1561       // Consume DOS EOL. It will be normalized in addComment.
1562       if (current_ != end_ && *current_ == '\n')
1563         getNextChar();
1564       // Break on Moc OS 9 EOL.
1565       break;
1566     }
1567   }
1568   return true;
1569 }
1570 
readNumber(bool checkInf)1571 bool OurReader::readNumber(bool checkInf) {
1572   const char *p = current_;
1573   if (checkInf && p != end_ && *p == 'I') {
1574     current_ = ++p;
1575     return false;
1576   }
1577   char c = '0'; // stopgap for already consumed character
1578   // integral part
1579   while (c >= '0' && c <= '9')
1580     c = (current_ = p) < end_ ? *p++ : 0;
1581   // fractional part
1582   if (c == '.') {
1583     c = (current_ = p) < end_ ? *p++ : 0;
1584     while (c >= '0' && c <= '9')
1585       c = (current_ = p) < end_ ? *p++ : 0;
1586   }
1587   // exponential part
1588   if (c == 'e' || c == 'E') {
1589     c = (current_ = p) < end_ ? *p++ : 0;
1590     if (c == '+' || c == '-')
1591       c = (current_ = p) < end_ ? *p++ : 0;
1592     while (c >= '0' && c <= '9')
1593       c = (current_ = p) < end_ ? *p++ : 0;
1594   }
1595   return true;
1596 }
readString()1597 bool OurReader::readString() {
1598   Char c = 0;
1599   while (current_ != end_) {
1600     c = getNextChar();
1601     if (c == '\\')
1602       getNextChar();
1603     else if (c == '"')
1604       break;
1605   }
1606   return c == '"';
1607 }
1608 
1609 
readStringSingleQuote()1610 bool OurReader::readStringSingleQuote() {
1611   Char c = 0;
1612   while (current_ != end_) {
1613     c = getNextChar();
1614     if (c == '\\')
1615       getNextChar();
1616     else if (c == '\'')
1617       break;
1618   }
1619   return c == '\'';
1620 }
1621 
readObject(Token & tokenStart)1622 bool OurReader::readObject(Token& tokenStart) {
1623   Token tokenName;
1624   std::string name;
1625   Value init(objectValue);
1626   currentValue().swapPayload(init);
1627   currentValue().setOffsetStart(tokenStart.start_ - begin_);
1628   while (readToken(tokenName)) {
1629     bool initialTokenOk = true;
1630     while (tokenName.type_ == tokenComment && initialTokenOk)
1631       initialTokenOk = readToken(tokenName);
1632     if (!initialTokenOk)
1633       break;
1634     if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
1635       return true;
1636     name = "";
1637     if (tokenName.type_ == tokenString) {
1638       if (!decodeString(tokenName, name))
1639         return recoverFromError(tokenObjectEnd);
1640     } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
1641       Value numberName;
1642       if (!decodeNumber(tokenName, numberName))
1643         return recoverFromError(tokenObjectEnd);
1644       name = numberName.asString();
1645     } else {
1646       break;
1647     }
1648 
1649     Token colon;
1650     if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
1651       return addErrorAndRecover(
1652           "Missing ':' after object member name", colon, tokenObjectEnd);
1653     }
1654     if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
1655     if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
1656       std::string msg = "Duplicate key: '" + name + "'";
1657       return addErrorAndRecover(
1658           msg, tokenName, tokenObjectEnd);
1659     }
1660     Value& value = currentValue()[name];
1661     nodes_.push(&value);
1662     bool ok = readValue();
1663     nodes_.pop();
1664     if (!ok) // error already set
1665       return recoverFromError(tokenObjectEnd);
1666 
1667     Token comma;
1668     if (!readToken(comma) ||
1669         (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1670          comma.type_ != tokenComment)) {
1671       return addErrorAndRecover(
1672           "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1673     }
1674     bool finalizeTokenOk = true;
1675     while (comma.type_ == tokenComment && finalizeTokenOk)
1676       finalizeTokenOk = readToken(comma);
1677     if (comma.type_ == tokenObjectEnd)
1678       return true;
1679   }
1680   return addErrorAndRecover(
1681       "Missing '}' or object member name", tokenName, tokenObjectEnd);
1682 }
1683 
readArray(Token & tokenStart)1684 bool OurReader::readArray(Token& tokenStart) {
1685   Value init(arrayValue);
1686   currentValue().swapPayload(init);
1687   currentValue().setOffsetStart(tokenStart.start_ - begin_);
1688   skipSpaces();
1689   if (*current_ == ']') // empty array
1690   {
1691     Token endArray;
1692     readToken(endArray);
1693     return true;
1694   }
1695   int index = 0;
1696   for (;;) {
1697     Value& value = currentValue()[index++];
1698     nodes_.push(&value);
1699     bool ok = readValue();
1700     nodes_.pop();
1701     if (!ok) // error already set
1702       return recoverFromError(tokenArrayEnd);
1703 
1704     Token token;
1705     // Accept Comment after last item in the array.
1706     ok = readToken(token);
1707     while (token.type_ == tokenComment && ok) {
1708       ok = readToken(token);
1709     }
1710     bool badTokenType =
1711         (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1712     if (!ok || badTokenType) {
1713       return addErrorAndRecover(
1714           "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1715     }
1716     if (token.type_ == tokenArrayEnd)
1717       break;
1718   }
1719   return true;
1720 }
1721 
decodeNumber(Token & token)1722 bool OurReader::decodeNumber(Token& token) {
1723   Value decoded;
1724   if (!decodeNumber(token, decoded))
1725     return false;
1726   currentValue().swapPayload(decoded);
1727   currentValue().setOffsetStart(token.start_ - begin_);
1728   currentValue().setOffsetLimit(token.end_ - begin_);
1729   return true;
1730 }
1731 
decodeNumber(Token & token,Value & decoded)1732 bool OurReader::decodeNumber(Token& token, Value& decoded) {
1733   // Attempts to parse the number as an integer. If the number is
1734   // larger than the maximum supported value of an integer then
1735   // we decode the number as a double.
1736   Location current = token.start_;
1737   bool isNegative = *current == '-';
1738   if (isNegative)
1739     ++current;
1740   // TODO: Help the compiler do the div and mod at compile time or get rid of them.
1741   Value::LargestUInt maxIntegerValue =
1742       isNegative ? Value::LargestUInt(-Value::minLargestInt)
1743                  : Value::maxLargestUInt;
1744   Value::LargestUInt threshold = maxIntegerValue / 10;
1745   Value::LargestUInt value = 0;
1746   while (current < token.end_) {
1747     Char c = *current++;
1748     if (c < '0' || c > '9')
1749       return decodeDouble(token, decoded);
1750     Value::UInt digit(c - '0');
1751     if (value >= threshold) {
1752       // We've hit or exceeded the max value divided by 10 (rounded down). If
1753       // a) we've only just touched the limit, b) this is the last digit, and
1754       // c) it's small enough to fit in that rounding delta, we're okay.
1755       // Otherwise treat this number as a double to avoid overflow.
1756       if (value > threshold || current != token.end_ ||
1757           digit > maxIntegerValue % 10) {
1758         return decodeDouble(token, decoded);
1759       }
1760     }
1761     value = value * 10 + digit;
1762   }
1763   if (isNegative)
1764     decoded = -Value::LargestInt(value);
1765   else if (value <= Value::LargestUInt(Value::maxInt))
1766     decoded = Value::LargestInt(value);
1767   else
1768     decoded = value;
1769   return true;
1770 }
1771 
decodeDouble(Token & token)1772 bool OurReader::decodeDouble(Token& token) {
1773   Value decoded;
1774   if (!decodeDouble(token, decoded))
1775     return false;
1776   currentValue().swapPayload(decoded);
1777   currentValue().setOffsetStart(token.start_ - begin_);
1778   currentValue().setOffsetLimit(token.end_ - begin_);
1779   return true;
1780 }
1781 
decodeDouble(Token & token,Value & decoded)1782 bool OurReader::decodeDouble(Token& token, Value& decoded) {
1783   double value = 0;
1784   const int bufferSize = 32;
1785   int count;
1786   int length = int(token.end_ - token.start_);
1787 
1788   // Sanity check to avoid buffer overflow exploits.
1789   if (length < 0) {
1790     return addError("Unable to parse token length", token);
1791   }
1792 
1793   // Avoid using a string constant for the format control string given to
1794   // sscanf, as this can cause hard to debug crashes on OS X. See here for more
1795   // info:
1796   //
1797   //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
1798   char format[] = "%lf";
1799 
1800   if (length <= bufferSize) {
1801     Char buffer[bufferSize + 1];
1802     memcpy(buffer, token.start_, length);
1803     buffer[length] = 0;
1804     count = sscanf(buffer, format, &value);
1805   } else {
1806     std::string buffer(token.start_, token.end_);
1807     count = sscanf(buffer.c_str(), format, &value);
1808   }
1809 
1810   if (count != 1)
1811     return addError("'" + std::string(token.start_, token.end_) +
1812                         "' is not a number.",
1813                     token);
1814   decoded = value;
1815   return true;
1816 }
1817 
decodeString(Token & token)1818 bool OurReader::decodeString(Token& token) {
1819   std::string decoded_string;
1820   if (!decodeString(token, decoded_string))
1821     return false;
1822   Value decoded(decoded_string);
1823   currentValue().swapPayload(decoded);
1824   currentValue().setOffsetStart(token.start_ - begin_);
1825   currentValue().setOffsetLimit(token.end_ - begin_);
1826   return true;
1827 }
1828 
decodeString(Token & token,std::string & decoded)1829 bool OurReader::decodeString(Token& token, std::string& decoded) {
1830   decoded.reserve(token.end_ - token.start_ - 2);
1831   Location current = token.start_ + 1; // skip '"'
1832   Location end = token.end_ - 1;       // do not include '"'
1833   while (current != end) {
1834     Char c = *current++;
1835     if (c == '"')
1836       break;
1837     else if (c == '\\') {
1838       if (current == end)
1839         return addError("Empty escape sequence in string", token, current);
1840       Char escape = *current++;
1841       switch (escape) {
1842       case '"':
1843         decoded += '"';
1844         break;
1845       case '/':
1846         decoded += '/';
1847         break;
1848       case '\\':
1849         decoded += '\\';
1850         break;
1851       case 'b':
1852         decoded += '\b';
1853         break;
1854       case 'f':
1855         decoded += '\f';
1856         break;
1857       case 'n':
1858         decoded += '\n';
1859         break;
1860       case 'r':
1861         decoded += '\r';
1862         break;
1863       case 't':
1864         decoded += '\t';
1865         break;
1866       case 'u': {
1867         unsigned int unicode;
1868         if (!decodeUnicodeCodePoint(token, current, end, unicode))
1869           return false;
1870         decoded += codePointToUTF8(unicode);
1871       } break;
1872       default:
1873         return addError("Bad escape sequence in string", token, current);
1874       }
1875     } else {
1876       decoded += c;
1877     }
1878   }
1879   return true;
1880 }
1881 
decodeUnicodeCodePoint(Token & token,Location & current,Location end,unsigned int & unicode)1882 bool OurReader::decodeUnicodeCodePoint(Token& token,
1883                                     Location& current,
1884                                     Location end,
1885                                     unsigned int& unicode) {
1886 
1887   if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
1888     return false;
1889   if (unicode >= 0xD800 && unicode <= 0xDBFF) {
1890     // surrogate pairs
1891     if (end - current < 6)
1892       return addError(
1893           "additional six characters expected to parse unicode surrogate pair.",
1894           token,
1895           current);
1896     unsigned int surrogatePair;
1897     if (*(current++) == '\\' && *(current++) == 'u') {
1898       if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
1899         unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1900       } else
1901         return false;
1902     } else
1903       return addError("expecting another \\u token to begin the second half of "
1904                       "a unicode surrogate pair",
1905                       token,
1906                       current);
1907   }
1908   return true;
1909 }
1910 
decodeUnicodeEscapeSequence(Token & token,Location & current,Location end,unsigned int & unicode)1911 bool OurReader::decodeUnicodeEscapeSequence(Token& token,
1912                                          Location& current,
1913                                          Location end,
1914                                          unsigned int& unicode) {
1915   if (end - current < 4)
1916     return addError(
1917         "Bad unicode escape sequence in string: four digits expected.",
1918         token,
1919         current);
1920   unicode = 0;
1921   for (int index = 0; index < 4; ++index) {
1922     Char c = *current++;
1923     unicode *= 16;
1924     if (c >= '0' && c <= '9')
1925       unicode += c - '0';
1926     else if (c >= 'a' && c <= 'f')
1927       unicode += c - 'a' + 10;
1928     else if (c >= 'A' && c <= 'F')
1929       unicode += c - 'A' + 10;
1930     else
1931       return addError(
1932           "Bad unicode escape sequence in string: hexadecimal digit expected.",
1933           token,
1934           current);
1935   }
1936   return true;
1937 }
1938 
1939 bool
addError(const std::string & message,Token & token,Location extra)1940 OurReader::addError(const std::string& message, Token& token, Location extra) {
1941   ErrorInfo info;
1942   info.token_ = token;
1943   info.message_ = message;
1944   info.extra_ = extra;
1945   errors_.push_back(info);
1946   return false;
1947 }
1948 
recoverFromError(TokenType skipUntilToken)1949 bool OurReader::recoverFromError(TokenType skipUntilToken) {
1950   int errorCount = int(errors_.size());
1951   Token skip;
1952   for (;;) {
1953     if (!readToken(skip))
1954       errors_.resize(errorCount); // discard errors caused by recovery
1955     if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
1956       break;
1957   }
1958   errors_.resize(errorCount);
1959   return false;
1960 }
1961 
addErrorAndRecover(const std::string & message,Token & token,TokenType skipUntilToken)1962 bool OurReader::addErrorAndRecover(const std::string& message,
1963                                 Token& token,
1964                                 TokenType skipUntilToken) {
1965   addError(message, token);
1966   return recoverFromError(skipUntilToken);
1967 }
1968 
currentValue()1969 Value& OurReader::currentValue() { return *(nodes_.top()); }
1970 
getNextChar()1971 OurReader::Char OurReader::getNextChar() {
1972   if (current_ == end_)
1973     return 0;
1974   return *current_++;
1975 }
1976 
getLocationLineAndColumn(Location location,int & line,int & column) const1977 void OurReader::getLocationLineAndColumn(Location location,
1978                                       int& line,
1979                                       int& column) const {
1980   Location current = begin_;
1981   Location lastLineStart = current;
1982   line = 0;
1983   while (current < location && current != end_) {
1984     Char c = *current++;
1985     if (c == '\r') {
1986       if (*current == '\n')
1987         ++current;
1988       lastLineStart = current;
1989       ++line;
1990     } else if (c == '\n') {
1991       lastLineStart = current;
1992       ++line;
1993     }
1994   }
1995   // column & line start at 1
1996   column = int(location - lastLineStart) + 1;
1997   ++line;
1998 }
1999 
getLocationLineAndColumn(Location location) const2000 std::string OurReader::getLocationLineAndColumn(Location location) const {
2001   int line, column;
2002   getLocationLineAndColumn(location, line, column);
2003   char buffer[18 + 16 + 16 + 1];
2004   snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
2005   return buffer;
2006 }
2007 
getFormattedErrorMessages() const2008 std::string OurReader::getFormattedErrorMessages() const {
2009   std::string formattedMessage;
2010   for (Errors::const_iterator itError = errors_.begin();
2011        itError != errors_.end();
2012        ++itError) {
2013     const ErrorInfo& error = *itError;
2014     formattedMessage +=
2015         "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
2016     formattedMessage += "  " + error.message_ + "\n";
2017     if (error.extra_)
2018       formattedMessage +=
2019           "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
2020   }
2021   return formattedMessage;
2022 }
2023 
getStructuredErrors() const2024 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
2025   std::vector<OurReader::StructuredError> allErrors;
2026   for (Errors::const_iterator itError = errors_.begin();
2027        itError != errors_.end();
2028        ++itError) {
2029     const ErrorInfo& error = *itError;
2030     OurReader::StructuredError structured;
2031     structured.offset_start = error.token_.start_ - begin_;
2032     structured.offset_limit = error.token_.end_ - begin_;
2033     structured.message = error.message_;
2034     allErrors.push_back(structured);
2035   }
2036   return allErrors;
2037 }
2038 
pushError(const Value & value,const std::string & message)2039 bool OurReader::pushError(const Value& value, const std::string& message) {
2040   size_t length = end_ - begin_;
2041   if(value.getOffsetStart() > length
2042     || value.getOffsetLimit() > length)
2043     return false;
2044   Token token;
2045   token.type_ = tokenError;
2046   token.start_ = begin_ + value.getOffsetStart();
2047   token.end_ = end_ + value.getOffsetLimit();
2048   ErrorInfo info;
2049   info.token_ = token;
2050   info.message_ = message;
2051   info.extra_ = 0;
2052   errors_.push_back(info);
2053   return true;
2054 }
2055 
pushError(const Value & value,const std::string & message,const Value & extra)2056 bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
2057   size_t length = end_ - begin_;
2058   if(value.getOffsetStart() > length
2059     || value.getOffsetLimit() > length
2060     || extra.getOffsetLimit() > length)
2061     return false;
2062   Token token;
2063   token.type_ = tokenError;
2064   token.start_ = begin_ + value.getOffsetStart();
2065   token.end_ = begin_ + value.getOffsetLimit();
2066   ErrorInfo info;
2067   info.token_ = token;
2068   info.message_ = message;
2069   info.extra_ = begin_ + extra.getOffsetStart();
2070   errors_.push_back(info);
2071   return true;
2072 }
2073 
good() const2074 bool OurReader::good() const {
2075   return !errors_.size();
2076 }
2077 
2078 
2079 class OurCharReader : public CharReader {
2080   bool const collectComments_;
2081   OurReader reader_;
2082 public:
OurCharReader(bool collectComments,OurFeatures const & features)2083   OurCharReader(
2084     bool collectComments,
2085     OurFeatures const& features)
2086   : collectComments_(collectComments)
2087   , reader_(features)
2088   {}
parse(char const * beginDoc,char const * endDoc,Value * root,std::string * errs)2089   bool parse(
2090       char const* beginDoc, char const* endDoc,
2091       Value* root, std::string* errs) override {
2092     bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
2093     if (errs) {
2094       *errs = reader_.getFormattedErrorMessages();
2095     }
2096     return ok;
2097   }
2098 };
2099 
CharReaderBuilder()2100 CharReaderBuilder::CharReaderBuilder()
2101 {
2102   setDefaults(&settings_);
2103 }
~CharReaderBuilder()2104 CharReaderBuilder::~CharReaderBuilder()
2105 {}
newCharReader() const2106 CharReader* CharReaderBuilder::newCharReader() const
2107 {
2108   bool collectComments = settings_["collectComments"].asBool();
2109   OurFeatures features = OurFeatures::all();
2110   features.allowComments_ = settings_["allowComments"].asBool();
2111   features.strictRoot_ = settings_["strictRoot"].asBool();
2112   features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
2113   features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
2114   features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
2115   features.stackLimit_ = settings_["stackLimit"].asInt();
2116   features.failIfExtra_ = settings_["failIfExtra"].asBool();
2117   features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
2118   features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
2119   return new OurCharReader(collectComments, features);
2120 }
getValidReaderKeys(std::set<std::string> * valid_keys)2121 static void getValidReaderKeys(std::set<std::string>* valid_keys)
2122 {
2123   valid_keys->clear();
2124   valid_keys->insert("collectComments");
2125   valid_keys->insert("allowComments");
2126   valid_keys->insert("strictRoot");
2127   valid_keys->insert("allowDroppedNullPlaceholders");
2128   valid_keys->insert("allowNumericKeys");
2129   valid_keys->insert("allowSingleQuotes");
2130   valid_keys->insert("stackLimit");
2131   valid_keys->insert("failIfExtra");
2132   valid_keys->insert("rejectDupKeys");
2133   valid_keys->insert("allowSpecialFloats");
2134 }
validate(Json::Value * invalid) const2135 bool CharReaderBuilder::validate(Json::Value* invalid) const
2136 {
2137   Json::Value my_invalid;
2138   if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
2139   Json::Value& inv = *invalid;
2140   std::set<std::string> valid_keys;
2141   getValidReaderKeys(&valid_keys);
2142   Value::Members keys = settings_.getMemberNames();
2143   size_t n = keys.size();
2144   for (size_t i = 0; i < n; ++i) {
2145     std::string const& key = keys[i];
2146     if (valid_keys.find(key) == valid_keys.end()) {
2147       inv[key] = settings_[key];
2148     }
2149   }
2150   return 0u == inv.size();
2151 }
operator [](std::string key)2152 Value& CharReaderBuilder::operator[](std::string key)
2153 {
2154   return settings_[key];
2155 }
2156 // static
strictMode(Json::Value * settings)2157 void CharReaderBuilder::strictMode(Json::Value* settings)
2158 {
2159 //! [CharReaderBuilderStrictMode]
2160   (*settings)["allowComments"] = false;
2161   (*settings)["strictRoot"] = true;
2162   (*settings)["allowDroppedNullPlaceholders"] = false;
2163   (*settings)["allowNumericKeys"] = false;
2164   (*settings)["allowSingleQuotes"] = false;
2165   (*settings)["stackLimit"] = 1000;
2166   (*settings)["failIfExtra"] = true;
2167   (*settings)["rejectDupKeys"] = true;
2168   (*settings)["allowSpecialFloats"] = false;
2169 //! [CharReaderBuilderStrictMode]
2170 }
2171 // static
setDefaults(Json::Value * settings)2172 void CharReaderBuilder::setDefaults(Json::Value* settings)
2173 {
2174 //! [CharReaderBuilderDefaults]
2175   (*settings)["collectComments"] = true;
2176   (*settings)["allowComments"] = true;
2177   (*settings)["strictRoot"] = false;
2178   (*settings)["allowDroppedNullPlaceholders"] = false;
2179   (*settings)["allowNumericKeys"] = false;
2180   (*settings)["allowSingleQuotes"] = false;
2181   (*settings)["stackLimit"] = 1000;
2182   (*settings)["failIfExtra"] = false;
2183   (*settings)["rejectDupKeys"] = false;
2184   (*settings)["allowSpecialFloats"] = false;
2185 //! [CharReaderBuilderDefaults]
2186 }
2187 
2188 //////////////////////////////////
2189 // global functions
2190 
parseFromStream(CharReader::Factory const & fact,std::istream & sin,Value * root,std::string * errs)2191 bool parseFromStream(
2192     CharReader::Factory const& fact, std::istream& sin,
2193     Value* root, std::string* errs)
2194 {
2195   std::ostringstream ssin;
2196   ssin << sin.rdbuf();
2197   std::string doc = ssin.str();
2198   char const* begin = doc.data();
2199   char const* end = begin + doc.size();
2200   // Note that we do not actually need a null-terminator.
2201   CharReaderPtr const reader(fact.newCharReader());
2202   return reader->parse(begin, end, root, errs);
2203 }
2204 
operator >>(std::istream & sin,Value & root)2205 std::istream& operator>>(std::istream& sin, Value& root) {
2206   CharReaderBuilder b;
2207   std::string errs;
2208   bool ok = parseFromStream(b, sin, &root, &errs);
2209   if (!ok) {
2210     fprintf(stderr,
2211             "Error from reader: %s",
2212             errs.c_str());
2213 
2214     throwRuntimeError(errs);
2215   }
2216   return sin;
2217 }
2218 
2219 } // namespace Json
2220 
2221 // //////////////////////////////////////////////////////////////////////
2222 // End of content of file: src/lib_json/json_reader.cpp
2223 // //////////////////////////////////////////////////////////////////////
2224 
2225 
2226 
2227 
2228 
2229 
2230 // //////////////////////////////////////////////////////////////////////
2231 // Beginning of content of file: src/lib_json/json_valueiterator.inl
2232 // //////////////////////////////////////////////////////////////////////
2233 
2234 // Copyright 2007-2010 Baptiste Lepilleur
2235 // Distributed under MIT license, or public domain if desired and
2236 // recognized in your jurisdiction.
2237 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2238 
2239 // included by json_value.cpp
2240 
2241 namespace Json {
2242 
2243 // //////////////////////////////////////////////////////////////////
2244 // //////////////////////////////////////////////////////////////////
2245 // //////////////////////////////////////////////////////////////////
2246 // class ValueIteratorBase
2247 // //////////////////////////////////////////////////////////////////
2248 // //////////////////////////////////////////////////////////////////
2249 // //////////////////////////////////////////////////////////////////
2250 
ValueIteratorBase()2251 ValueIteratorBase::ValueIteratorBase()
2252     : current_(), isNull_(true) {
2253 }
2254 
ValueIteratorBase(const Value::ObjectValues::iterator & current)2255 ValueIteratorBase::ValueIteratorBase(
2256     const Value::ObjectValues::iterator& current)
2257     : current_(current), isNull_(false) {}
2258 
deref() const2259 Value& ValueIteratorBase::deref() const {
2260   return current_->second;
2261 }
2262 
increment()2263 void ValueIteratorBase::increment() {
2264   ++current_;
2265 }
2266 
decrement()2267 void ValueIteratorBase::decrement() {
2268   --current_;
2269 }
2270 
2271 ValueIteratorBase::difference_type
computeDistance(const SelfType & other) const2272 ValueIteratorBase::computeDistance(const SelfType& other) const {
2273 #ifdef JSON_USE_CPPTL_SMALLMAP
2274   return other.current_ - current_;
2275 #else
2276   // Iterator for null value are initialized using the default
2277   // constructor, which initialize current_ to the default
2278   // std::map::iterator. As begin() and end() are two instance
2279   // of the default std::map::iterator, they can not be compared.
2280   // To allow this, we handle this comparison specifically.
2281   if (isNull_ && other.isNull_) {
2282     return 0;
2283   }
2284 
2285   // Usage of std::distance is not portable (does not compile with Sun Studio 12
2286   // RogueWave STL,
2287   // which is the one used by default).
2288   // Using a portable hand-made version for non random iterator instead:
2289   //   return difference_type( std::distance( current_, other.current_ ) );
2290   difference_type myDistance = 0;
2291   for (Value::ObjectValues::iterator it = current_; it != other.current_;
2292        ++it) {
2293     ++myDistance;
2294   }
2295   return myDistance;
2296 #endif
2297 }
2298 
isEqual(const SelfType & other) const2299 bool ValueIteratorBase::isEqual(const SelfType& other) const {
2300   if (isNull_) {
2301     return other.isNull_;
2302   }
2303   return current_ == other.current_;
2304 }
2305 
copy(const SelfType & other)2306 void ValueIteratorBase::copy(const SelfType& other) {
2307   current_ = other.current_;
2308   isNull_ = other.isNull_;
2309 }
2310 
key() const2311 Value ValueIteratorBase::key() const {
2312   const Value::CZString czstring = (*current_).first;
2313   if (czstring.data()) {
2314     if (czstring.isStaticString())
2315       return Value(StaticString(czstring.data()));
2316     return Value(czstring.data(), czstring.data() + czstring.length());
2317   }
2318   return Value(czstring.index());
2319 }
2320 
index() const2321 UInt ValueIteratorBase::index() const {
2322   const Value::CZString czstring = (*current_).first;
2323   if (!czstring.data())
2324     return czstring.index();
2325   return Value::UInt(-1);
2326 }
2327 
name() const2328 std::string ValueIteratorBase::name() const {
2329   char const* keey;
2330   char const* end;
2331   keey = memberName(&end);
2332   if (!keey) return std::string();
2333   return std::string(keey, end);
2334 }
2335 
memberName() const2336 char const* ValueIteratorBase::memberName() const {
2337   const char* cname = (*current_).first.data();
2338   return cname ? cname : "";
2339 }
2340 
memberName(char const ** end) const2341 char const* ValueIteratorBase::memberName(char const** end) const {
2342   const char* cname = (*current_).first.data();
2343   if (!cname) {
2344     *end = NULL;
2345     return NULL;
2346   }
2347   *end = cname + (*current_).first.length();
2348   return cname;
2349 }
2350 
2351 // //////////////////////////////////////////////////////////////////
2352 // //////////////////////////////////////////////////////////////////
2353 // //////////////////////////////////////////////////////////////////
2354 // class ValueConstIterator
2355 // //////////////////////////////////////////////////////////////////
2356 // //////////////////////////////////////////////////////////////////
2357 // //////////////////////////////////////////////////////////////////
2358 
ValueConstIterator()2359 ValueConstIterator::ValueConstIterator() {}
2360 
ValueConstIterator(const Value::ObjectValues::iterator & current)2361 ValueConstIterator::ValueConstIterator(
2362     const Value::ObjectValues::iterator& current)
2363     : ValueIteratorBase(current) {}
2364 
ValueConstIterator(ValueIterator const & other)2365 ValueConstIterator::ValueConstIterator(ValueIterator const& other)
2366     : ValueIteratorBase(other) {}
2367 
2368 ValueConstIterator& ValueConstIterator::
operator =(const ValueIteratorBase & other)2369 operator=(const ValueIteratorBase& other) {
2370   copy(other);
2371   return *this;
2372 }
2373 
2374 // //////////////////////////////////////////////////////////////////
2375 // //////////////////////////////////////////////////////////////////
2376 // //////////////////////////////////////////////////////////////////
2377 // class ValueIterator
2378 // //////////////////////////////////////////////////////////////////
2379 // //////////////////////////////////////////////////////////////////
2380 // //////////////////////////////////////////////////////////////////
2381 
ValueIterator()2382 ValueIterator::ValueIterator() {}
2383 
ValueIterator(const Value::ObjectValues::iterator & current)2384 ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
2385     : ValueIteratorBase(current) {}
2386 
ValueIterator(const ValueConstIterator & other)2387 ValueIterator::ValueIterator(const ValueConstIterator& other)
2388     : ValueIteratorBase(other) {
2389   throwRuntimeError("ConstIterator to Iterator should never be allowed.");
2390 }
2391 
ValueIterator(const ValueIterator & other)2392 ValueIterator::ValueIterator(const ValueIterator& other)
2393     : ValueIteratorBase(other) {}
2394 
operator =(const SelfType & other)2395 ValueIterator& ValueIterator::operator=(const SelfType& other) {
2396   copy(other);
2397   return *this;
2398 }
2399 
2400 } // namespace Json
2401 
2402 // //////////////////////////////////////////////////////////////////////
2403 // End of content of file: src/lib_json/json_valueiterator.inl
2404 // //////////////////////////////////////////////////////////////////////
2405 
2406 
2407 
2408 
2409 
2410 
2411 // //////////////////////////////////////////////////////////////////////
2412 // Beginning of content of file: src/lib_json/json_value.cpp
2413 // //////////////////////////////////////////////////////////////////////
2414 
2415 // Copyright 2011 Baptiste Lepilleur
2416 // Distributed under MIT license, or public domain if desired and
2417 // recognized in your jurisdiction.
2418 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2419 
2420 #if !defined(JSON_IS_AMALGAMATION)
2421 #include <json/assertions.h>
2422 #include <json/value.h>
2423 #include <json/writer.h>
2424 #endif // if !defined(JSON_IS_AMALGAMATION)
2425 #include <math.h>
2426 #include <sstream>
2427 #include <utility>
2428 #include <cstring>
2429 #include <cassert>
2430 #ifdef JSON_USE_CPPTL
2431 #include <cpptl/conststring.h>
2432 #endif
2433 #include <cstddef> // size_t
2434 #include <algorithm> // min()
2435 
2436 #define JSON_ASSERT_UNREACHABLE assert(false)
2437 
2438 namespace Json {
2439 
2440 // This is a walkaround to avoid the static initialization of Value::null.
2441 // kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
2442 // 8 (instead of 4) as a bit of future-proofing.
2443 #if defined(__ARMEL__)
2444 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
2445 #else
2446 #define ALIGNAS(byte_alignment)
2447 #endif
2448 static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
2449 const unsigned char& kNullRef = kNull[0];
2450 const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
2451 const Value& Value::nullRef = null;
2452 
2453 const Int Value::minInt = Int(~(UInt(-1) / 2));
2454 const Int Value::maxInt = Int(UInt(-1) / 2);
2455 const UInt Value::maxUInt = UInt(-1);
2456 #if defined(JSON_HAS_INT64)
2457 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
2458 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
2459 const UInt64 Value::maxUInt64 = UInt64(-1);
2460 // The constant is hard-coded because some compiler have trouble
2461 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
2462 // Assumes that UInt64 is a 64 bits integer.
2463 static const double maxUInt64AsDouble = 18446744073709551615.0;
2464 #endif // defined(JSON_HAS_INT64)
2465 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
2466 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
2467 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
2468 
2469 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2470 template <typename T, typename U>
InRange(double d,T min,U max)2471 static inline bool InRange(double d, T min, U max) {
2472   return d >= min && d <= max;
2473 }
2474 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
integerToDouble(Json::UInt64 value)2475 static inline double integerToDouble(Json::UInt64 value) {
2476   return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
2477 }
2478 
integerToDouble(T value)2479 template <typename T> static inline double integerToDouble(T value) {
2480   return static_cast<double>(value);
2481 }
2482 
2483 template <typename T, typename U>
InRange(double d,T min,U max)2484 static inline bool InRange(double d, T min, U max) {
2485   return d >= integerToDouble(min) && d <= integerToDouble(max);
2486 }
2487 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2488 
2489 /** Duplicates the specified string value.
2490  * @param value Pointer to the string to duplicate. Must be zero-terminated if
2491  *              length is "unknown".
2492  * @param length Length of the value. if equals to unknown, then it will be
2493  *               computed using strlen(value).
2494  * @return Pointer on the duplicate instance of string.
2495  */
duplicateStringValue(const char * value,size_t length)2496 static inline char* duplicateStringValue(const char* value,
2497                                          size_t length) {
2498   // Avoid an integer overflow in the call to malloc below by limiting length
2499   // to a sane value.
2500   if (length >= (size_t)Value::maxInt)
2501     length = Value::maxInt - 1;
2502 
2503   char* newString = static_cast<char*>(malloc(length + 1));
2504   if (newString == NULL) {
2505     throwRuntimeError(
2506         "in Json::Value::duplicateStringValue(): "
2507         "Failed to allocate string value buffer");
2508   }
2509   memcpy(newString, value, length);
2510   newString[length] = 0;
2511   return newString;
2512 }
2513 
2514 /* Record the length as a prefix.
2515  */
duplicateAndPrefixStringValue(const char * value,unsigned int length)2516 static inline char* duplicateAndPrefixStringValue(
2517     const char* value,
2518     unsigned int length)
2519 {
2520   // Avoid an integer overflow in the call to malloc below by limiting length
2521   // to a sane value.
2522   JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
2523                       "in Json::Value::duplicateAndPrefixStringValue(): "
2524                       "length too big for prefixing");
2525   unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
2526   char* newString = static_cast<char*>(malloc(actualLength));
2527   if (newString == 0) {
2528     throwRuntimeError(
2529         "in Json::Value::duplicateAndPrefixStringValue(): "
2530         "Failed to allocate string value buffer");
2531   }
2532   *reinterpret_cast<unsigned*>(newString) = length;
2533   memcpy(newString + sizeof(unsigned), value, length);
2534   newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
2535   return newString;
2536 }
decodePrefixedString(bool isPrefixed,char const * prefixed,unsigned * length,char const ** value)2537 inline static void decodePrefixedString(
2538     bool isPrefixed, char const* prefixed,
2539     unsigned* length, char const** value)
2540 {
2541   if (!isPrefixed) {
2542     *length = static_cast<unsigned>(strlen(prefixed));
2543     *value = prefixed;
2544   } else {
2545     *length = *reinterpret_cast<unsigned const*>(prefixed);
2546     *value = prefixed + sizeof(unsigned);
2547   }
2548 }
2549 /** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
2550  */
releaseStringValue(char * value)2551 static inline void releaseStringValue(char* value) { free(value); }
2552 
2553 } // namespace Json
2554 
2555 // //////////////////////////////////////////////////////////////////
2556 // //////////////////////////////////////////////////////////////////
2557 // //////////////////////////////////////////////////////////////////
2558 // ValueInternals...
2559 // //////////////////////////////////////////////////////////////////
2560 // //////////////////////////////////////////////////////////////////
2561 // //////////////////////////////////////////////////////////////////
2562 #if !defined(JSON_IS_AMALGAMATION)
2563 
2564 #include "json_valueiterator.inl"
2565 #endif // if !defined(JSON_IS_AMALGAMATION)
2566 
2567 namespace Json {
2568 
Exception(std::string const & msg)2569 Exception::Exception(std::string const& msg)
2570   : msg_(msg)
2571 {}
~Exception()2572 Exception::~Exception() throw()
2573 {}
what() const2574 char const* Exception::what() const throw()
2575 {
2576   return msg_.c_str();
2577 }
RuntimeError(std::string const & msg)2578 RuntimeError::RuntimeError(std::string const& msg)
2579   : Exception(msg)
2580 {}
LogicError(std::string const & msg)2581 LogicError::LogicError(std::string const& msg)
2582   : Exception(msg)
2583 {}
throwRuntimeError(std::string const & msg)2584 void throwRuntimeError(std::string const& msg)
2585 {
2586   throw RuntimeError(msg);
2587 }
throwLogicError(std::string const & msg)2588 void throwLogicError(std::string const& msg)
2589 {
2590   throw LogicError(msg);
2591 }
2592 
2593 // //////////////////////////////////////////////////////////////////
2594 // //////////////////////////////////////////////////////////////////
2595 // //////////////////////////////////////////////////////////////////
2596 // class Value::CommentInfo
2597 // //////////////////////////////////////////////////////////////////
2598 // //////////////////////////////////////////////////////////////////
2599 // //////////////////////////////////////////////////////////////////
2600 
CommentInfo()2601 Value::CommentInfo::CommentInfo() : comment_(0) {}
2602 
~CommentInfo()2603 Value::CommentInfo::~CommentInfo() {
2604   if (comment_)
2605     releaseStringValue(comment_);
2606 }
2607 
setComment(const char * text,size_t len)2608 void Value::CommentInfo::setComment(const char* text, size_t len) {
2609   if (comment_) {
2610     releaseStringValue(comment_);
2611     comment_ = 0;
2612   }
2613   JSON_ASSERT(text != 0);
2614   JSON_ASSERT_MESSAGE(
2615       text[0] == '\0' || text[0] == '/',
2616       "in Json::Value::setComment(): Comments must start with /");
2617   // It seems that /**/ style comments are acceptable as well.
2618   comment_ = duplicateStringValue(text, len);
2619 }
2620 
2621 // //////////////////////////////////////////////////////////////////
2622 // //////////////////////////////////////////////////////////////////
2623 // //////////////////////////////////////////////////////////////////
2624 // class Value::CZString
2625 // //////////////////////////////////////////////////////////////////
2626 // //////////////////////////////////////////////////////////////////
2627 // //////////////////////////////////////////////////////////////////
2628 
2629 // Notes: policy_ indicates if the string was allocated when
2630 // a string is stored.
2631 
CZString(ArrayIndex aindex)2632 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
2633 
CZString(char const * str,unsigned ulength,DuplicationPolicy allocate)2634 Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
2635     : cstr_(str) {
2636   // allocate != duplicate
2637   storage_.policy_ = allocate & 0x3;
2638   storage_.length_ = ulength & 0x3FFFFFFF;
2639 }
2640 
CZString(const CZString & other)2641 Value::CZString::CZString(const CZString& other)
2642     : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
2643                 ? duplicateStringValue(other.cstr_, other.storage_.length_)
2644                 : other.cstr_) {
2645   storage_.policy_ = (other.cstr_
2646                  ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
2647                      ? noDuplication : duplicate)
2648                  : static_cast<DuplicationPolicy>(other.storage_.policy_));
2649   storage_.length_ = other.storage_.length_;
2650 }
2651 
2652 #if JSON_HAS_RVALUE_REFERENCES
CZString(CZString && other)2653 Value::CZString::CZString(CZString&& other)
2654   : cstr_(other.cstr_), index_(other.index_) {
2655   other.cstr_ = nullptr;
2656 }
2657 #endif
2658 
~CZString()2659 Value::CZString::~CZString() {
2660   if (cstr_ && storage_.policy_ == duplicate)
2661     releaseStringValue(const_cast<char*>(cstr_));
2662 }
2663 
swap(CZString & other)2664 void Value::CZString::swap(CZString& other) {
2665   std::swap(cstr_, other.cstr_);
2666   std::swap(index_, other.index_);
2667 }
2668 
operator =(CZString other)2669 Value::CZString& Value::CZString::operator=(CZString other) {
2670   swap(other);
2671   return *this;
2672 }
2673 
operator <(const CZString & other) const2674 bool Value::CZString::operator<(const CZString& other) const {
2675   if (!cstr_) return index_ < other.index_;
2676   //return strcmp(cstr_, other.cstr_) < 0;
2677   // Assume both are strings.
2678   unsigned this_len = this->storage_.length_;
2679   unsigned other_len = other.storage_.length_;
2680   unsigned min_len = std::min(this_len, other_len);
2681   int comp = memcmp(this->cstr_, other.cstr_, min_len);
2682   if (comp < 0) return true;
2683   if (comp > 0) return false;
2684   return (this_len < other_len);
2685 }
2686 
operator ==(const CZString & other) const2687 bool Value::CZString::operator==(const CZString& other) const {
2688   if (!cstr_) return index_ == other.index_;
2689   //return strcmp(cstr_, other.cstr_) == 0;
2690   // Assume both are strings.
2691   unsigned this_len = this->storage_.length_;
2692   unsigned other_len = other.storage_.length_;
2693   if (this_len != other_len) return false;
2694   int comp = memcmp(this->cstr_, other.cstr_, this_len);
2695   return comp == 0;
2696 }
2697 
index() const2698 ArrayIndex Value::CZString::index() const { return index_; }
2699 
2700 //const char* Value::CZString::c_str() const { return cstr_; }
data() const2701 const char* Value::CZString::data() const { return cstr_; }
length() const2702 unsigned Value::CZString::length() const { return storage_.length_; }
isStaticString() const2703 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
2704 
2705 // //////////////////////////////////////////////////////////////////
2706 // //////////////////////////////////////////////////////////////////
2707 // //////////////////////////////////////////////////////////////////
2708 // class Value::Value
2709 // //////////////////////////////////////////////////////////////////
2710 // //////////////////////////////////////////////////////////////////
2711 // //////////////////////////////////////////////////////////////////
2712 
2713 /*! \internal Default constructor initialization must be equivalent to:
2714  * memset( this, 0, sizeof(Value) )
2715  * This optimization is used in ValueInternalMap fast allocator.
2716  */
Value(ValueType vtype)2717 Value::Value(ValueType vtype) {
2718   initBasic(vtype);
2719   switch (vtype) {
2720   case nullValue:
2721     break;
2722   case intValue:
2723   case uintValue:
2724     value_.int_ = 0;
2725     break;
2726   case realValue:
2727     value_.real_ = 0.0;
2728     break;
2729   case stringValue:
2730     value_.string_ = 0;
2731     break;
2732   case arrayValue:
2733   case objectValue:
2734     value_.map_ = new ObjectValues();
2735     break;
2736   case booleanValue:
2737     value_.bool_ = false;
2738     break;
2739   default:
2740     JSON_ASSERT_UNREACHABLE;
2741   }
2742 }
2743 
Value(Int value)2744 Value::Value(Int value) {
2745   initBasic(intValue);
2746   value_.int_ = value;
2747 }
2748 
Value(UInt value)2749 Value::Value(UInt value) {
2750   initBasic(uintValue);
2751   value_.uint_ = value;
2752 }
2753 #if defined(JSON_HAS_INT64)
Value(Int64 value)2754 Value::Value(Int64 value) {
2755   initBasic(intValue);
2756   value_.int_ = value;
2757 }
Value(UInt64 value)2758 Value::Value(UInt64 value) {
2759   initBasic(uintValue);
2760   value_.uint_ = value;
2761 }
2762 #endif // defined(JSON_HAS_INT64)
2763 
Value(double value)2764 Value::Value(double value) {
2765   initBasic(realValue);
2766   value_.real_ = value;
2767 }
2768 
Value(const char * value)2769 Value::Value(const char* value) {
2770   initBasic(stringValue, true);
2771   value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
2772 }
2773 
Value(const char * beginValue,const char * endValue)2774 Value::Value(const char* beginValue, const char* endValue) {
2775   initBasic(stringValue, true);
2776   value_.string_ =
2777       duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
2778 }
2779 
Value(const std::string & value)2780 Value::Value(const std::string& value) {
2781   initBasic(stringValue, true);
2782   value_.string_ =
2783       duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
2784 }
2785 
Value(const StaticString & value)2786 Value::Value(const StaticString& value) {
2787   initBasic(stringValue);
2788   value_.string_ = const_cast<char*>(value.c_str());
2789 }
2790 
2791 #ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString & value)2792 Value::Value(const CppTL::ConstString& value) {
2793   initBasic(stringValue, true);
2794   value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
2795 }
2796 #endif
2797 
Value(bool value)2798 Value::Value(bool value) {
2799   initBasic(booleanValue);
2800   value_.bool_ = value;
2801 }
2802 
Value(Value const & other)2803 Value::Value(Value const& other)
2804     : type_(other.type_), allocated_(false)
2805       ,
2806       comments_(0), start_(other.start_), limit_(other.limit_)
2807 {
2808   switch (type_) {
2809   case nullValue:
2810   case intValue:
2811   case uintValue:
2812   case realValue:
2813   case booleanValue:
2814     value_ = other.value_;
2815     break;
2816   case stringValue:
2817     if (other.value_.string_ && other.allocated_) {
2818       unsigned len;
2819       char const* str;
2820       decodePrefixedString(other.allocated_, other.value_.string_,
2821           &len, &str);
2822       value_.string_ = duplicateAndPrefixStringValue(str, len);
2823       allocated_ = true;
2824     } else {
2825       value_.string_ = other.value_.string_;
2826       allocated_ = false;
2827     }
2828     break;
2829   case arrayValue:
2830   case objectValue:
2831     value_.map_ = new ObjectValues(*other.value_.map_);
2832     break;
2833   default:
2834     JSON_ASSERT_UNREACHABLE;
2835   }
2836   if (other.comments_) {
2837     comments_ = new CommentInfo[numberOfCommentPlacement];
2838     for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
2839       const CommentInfo& otherComment = other.comments_[comment];
2840       if (otherComment.comment_)
2841         comments_[comment].setComment(
2842             otherComment.comment_, strlen(otherComment.comment_));
2843     }
2844   }
2845 }
2846 
2847 #if JSON_HAS_RVALUE_REFERENCES
2848 // Move constructor
Value(Value && other)2849 Value::Value(Value&& other) {
2850   initBasic(nullValue);
2851   swap(other);
2852 }
2853 #endif
2854 
~Value()2855 Value::~Value() {
2856   switch (type_) {
2857   case nullValue:
2858   case intValue:
2859   case uintValue:
2860   case realValue:
2861   case booleanValue:
2862     break;
2863   case stringValue:
2864     if (allocated_)
2865       releaseStringValue(value_.string_);
2866     break;
2867   case arrayValue:
2868   case objectValue:
2869     delete value_.map_;
2870     break;
2871   default:
2872     JSON_ASSERT_UNREACHABLE;
2873   }
2874 
2875   if (comments_)
2876     delete[] comments_;
2877 }
2878 
operator =(Value other)2879 Value& Value::operator=(Value other) {
2880   swap(other);
2881   return *this;
2882 }
2883 
swapPayload(Value & other)2884 void Value::swapPayload(Value& other) {
2885   ValueType temp = type_;
2886   type_ = other.type_;
2887   other.type_ = temp;
2888   std::swap(value_, other.value_);
2889   int temp2 = allocated_;
2890   allocated_ = other.allocated_;
2891   other.allocated_ = temp2 & 0x1;
2892 }
2893 
swap(Value & other)2894 void Value::swap(Value& other) {
2895   swapPayload(other);
2896   std::swap(comments_, other.comments_);
2897   std::swap(start_, other.start_);
2898   std::swap(limit_, other.limit_);
2899 }
2900 
type() const2901 ValueType Value::type() const { return type_; }
2902 
compare(const Value & other) const2903 int Value::compare(const Value& other) const {
2904   if (*this < other)
2905     return -1;
2906   if (*this > other)
2907     return 1;
2908   return 0;
2909 }
2910 
operator <(const Value & other) const2911 bool Value::operator<(const Value& other) const {
2912   int typeDelta = type_ - other.type_;
2913   if (typeDelta)
2914     return typeDelta < 0 ? true : false;
2915   switch (type_) {
2916   case nullValue:
2917     return false;
2918   case intValue:
2919     return value_.int_ < other.value_.int_;
2920   case uintValue:
2921     return value_.uint_ < other.value_.uint_;
2922   case realValue:
2923     return value_.real_ < other.value_.real_;
2924   case booleanValue:
2925     return value_.bool_ < other.value_.bool_;
2926   case stringValue:
2927   {
2928     if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
2929       if (other.value_.string_) return true;
2930       else return false;
2931     }
2932     unsigned this_len;
2933     unsigned other_len;
2934     char const* this_str;
2935     char const* other_str;
2936     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
2937     decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
2938     unsigned min_len = std::min(this_len, other_len);
2939     int comp = memcmp(this_str, other_str, min_len);
2940     if (comp < 0) return true;
2941     if (comp > 0) return false;
2942     return (this_len < other_len);
2943   }
2944   case arrayValue:
2945   case objectValue: {
2946     int delta = int(value_.map_->size() - other.value_.map_->size());
2947     if (delta)
2948       return delta < 0;
2949     return (*value_.map_) < (*other.value_.map_);
2950   }
2951   default:
2952     JSON_ASSERT_UNREACHABLE;
2953   }
2954   return false; // unreachable
2955 }
2956 
operator <=(const Value & other) const2957 bool Value::operator<=(const Value& other) const { return !(other < *this); }
2958 
operator >=(const Value & other) const2959 bool Value::operator>=(const Value& other) const { return !(*this < other); }
2960 
operator >(const Value & other) const2961 bool Value::operator>(const Value& other) const { return other < *this; }
2962 
operator ==(const Value & other) const2963 bool Value::operator==(const Value& other) const {
2964   // if ( type_ != other.type_ )
2965   // GCC 2.95.3 says:
2966   // attempt to take address of bit-field structure member `Json::Value::type_'
2967   // Beats me, but a temp solves the problem.
2968   int temp = other.type_;
2969   if (type_ != temp)
2970     return false;
2971   switch (type_) {
2972   case nullValue:
2973     return true;
2974   case intValue:
2975     return value_.int_ == other.value_.int_;
2976   case uintValue:
2977     return value_.uint_ == other.value_.uint_;
2978   case realValue:
2979     return value_.real_ == other.value_.real_;
2980   case booleanValue:
2981     return value_.bool_ == other.value_.bool_;
2982   case stringValue:
2983   {
2984     if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
2985       return (value_.string_ == other.value_.string_);
2986     }
2987     unsigned this_len;
2988     unsigned other_len;
2989     char const* this_str;
2990     char const* other_str;
2991     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
2992     decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
2993     if (this_len != other_len) return false;
2994     int comp = memcmp(this_str, other_str, this_len);
2995     return comp == 0;
2996   }
2997   case arrayValue:
2998   case objectValue:
2999     return value_.map_->size() == other.value_.map_->size() &&
3000            (*value_.map_) == (*other.value_.map_);
3001   default:
3002     JSON_ASSERT_UNREACHABLE;
3003   }
3004   return false; // unreachable
3005 }
3006 
operator !=(const Value & other) const3007 bool Value::operator!=(const Value& other) const { return !(*this == other); }
3008 
asCString() const3009 const char* Value::asCString() const {
3010   JSON_ASSERT_MESSAGE(type_ == stringValue,
3011                       "in Json::Value::asCString(): requires stringValue");
3012   if (value_.string_ == 0) return 0;
3013   unsigned this_len;
3014   char const* this_str;
3015   decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3016   return this_str;
3017 }
3018 
getString(char const ** str,char const ** cend) const3019 bool Value::getString(char const** str, char const** cend) const {
3020   if (type_ != stringValue) return false;
3021   if (value_.string_ == 0) return false;
3022   unsigned length;
3023   decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
3024   *cend = *str + length;
3025   return true;
3026 }
3027 
asString() const3028 std::string Value::asString() const {
3029   switch (type_) {
3030   case nullValue:
3031     return "";
3032   case stringValue:
3033   {
3034     if (value_.string_ == 0) return "";
3035     unsigned this_len;
3036     char const* this_str;
3037     decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3038     return std::string(this_str, this_len);
3039   }
3040   case booleanValue:
3041     return value_.bool_ ? "true" : "false";
3042   case intValue:
3043     return valueToString(value_.int_);
3044   case uintValue:
3045     return valueToString(value_.uint_);
3046   case realValue:
3047     return valueToString(value_.real_);
3048   default:
3049     JSON_FAIL_MESSAGE("Type is not convertible to string");
3050   }
3051 }
3052 
3053 #ifdef JSON_USE_CPPTL
asConstString() const3054 CppTL::ConstString Value::asConstString() const {
3055   unsigned len;
3056   char const* str;
3057   decodePrefixedString(allocated_, value_.string_,
3058       &len, &str);
3059   return CppTL::ConstString(str, len);
3060 }
3061 #endif
3062 
asInt() const3063 Value::Int Value::asInt() const {
3064   switch (type_) {
3065   case intValue:
3066     JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
3067     return Int(value_.int_);
3068   case uintValue:
3069     JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
3070     return Int(value_.uint_);
3071   case realValue:
3072     JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
3073                         "double out of Int range");
3074     return Int(value_.real_);
3075   case nullValue:
3076     return 0;
3077   case booleanValue:
3078     return value_.bool_ ? 1 : 0;
3079   default:
3080     break;
3081   }
3082   JSON_FAIL_MESSAGE("Value is not convertible to Int.");
3083 }
3084 
asUInt() const3085 Value::UInt Value::asUInt() const {
3086   switch (type_) {
3087   case intValue:
3088     JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
3089     return UInt(value_.int_);
3090   case uintValue:
3091     JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
3092     return UInt(value_.uint_);
3093   case realValue:
3094     JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
3095                         "double out of UInt range");
3096     return UInt(value_.real_);
3097   case nullValue:
3098     return 0;
3099   case booleanValue:
3100     return value_.bool_ ? 1 : 0;
3101   default:
3102     break;
3103   }
3104   JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
3105 }
3106 
3107 #if defined(JSON_HAS_INT64)
3108 
asInt64() const3109 Value::Int64 Value::asInt64() const {
3110   switch (type_) {
3111   case intValue:
3112     return Int64(value_.int_);
3113   case uintValue:
3114     JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
3115     return Int64(value_.uint_);
3116   case realValue:
3117     JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
3118                         "double out of Int64 range");
3119     return Int64(value_.real_);
3120   case nullValue:
3121     return 0;
3122   case booleanValue:
3123     return value_.bool_ ? 1 : 0;
3124   default:
3125     break;
3126   }
3127   JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
3128 }
3129 
asUInt64() const3130 Value::UInt64 Value::asUInt64() const {
3131   switch (type_) {
3132   case intValue:
3133     JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
3134     return UInt64(value_.int_);
3135   case uintValue:
3136     return UInt64(value_.uint_);
3137   case realValue:
3138     JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
3139                         "double out of UInt64 range");
3140     return UInt64(value_.real_);
3141   case nullValue:
3142     return 0;
3143   case booleanValue:
3144     return value_.bool_ ? 1 : 0;
3145   default:
3146     break;
3147   }
3148   JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
3149 }
3150 #endif // if defined(JSON_HAS_INT64)
3151 
asLargestInt() const3152 LargestInt Value::asLargestInt() const {
3153 #if defined(JSON_NO_INT64)
3154   return asInt();
3155 #else
3156   return asInt64();
3157 #endif
3158 }
3159 
asLargestUInt() const3160 LargestUInt Value::asLargestUInt() const {
3161 #if defined(JSON_NO_INT64)
3162   return asUInt();
3163 #else
3164   return asUInt64();
3165 #endif
3166 }
3167 
asDouble() const3168 double Value::asDouble() const {
3169   switch (type_) {
3170   case intValue:
3171     return static_cast<double>(value_.int_);
3172   case uintValue:
3173 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3174     return static_cast<double>(value_.uint_);
3175 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3176     return integerToDouble(value_.uint_);
3177 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3178   case realValue:
3179     return value_.real_;
3180   case nullValue:
3181     return 0.0;
3182   case booleanValue:
3183     return value_.bool_ ? 1.0 : 0.0;
3184   default:
3185     break;
3186   }
3187   JSON_FAIL_MESSAGE("Value is not convertible to double.");
3188 }
3189 
asFloat() const3190 float Value::asFloat() const {
3191   switch (type_) {
3192   case intValue:
3193     return static_cast<float>(value_.int_);
3194   case uintValue:
3195 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3196     return static_cast<float>(value_.uint_);
3197 #else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3198     return integerToDouble(value_.uint_);
3199 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3200   case realValue:
3201     return static_cast<float>(value_.real_);
3202   case nullValue:
3203     return 0.0;
3204   case booleanValue:
3205     return value_.bool_ ? 1.0f : 0.0f;
3206   default:
3207     break;
3208   }
3209   JSON_FAIL_MESSAGE("Value is not convertible to float.");
3210 }
3211 
asBool() const3212 bool Value::asBool() const {
3213   switch (type_) {
3214   case booleanValue:
3215     return value_.bool_;
3216   case nullValue:
3217     return false;
3218   case intValue:
3219     return value_.int_ ? true : false;
3220   case uintValue:
3221     return value_.uint_ ? true : false;
3222   case realValue:
3223     // This is kind of strange. Not recommended.
3224     return (value_.real_ != 0.0) ? true : false;
3225   default:
3226     break;
3227   }
3228   JSON_FAIL_MESSAGE("Value is not convertible to bool.");
3229 }
3230 
isConvertibleTo(ValueType other) const3231 bool Value::isConvertibleTo(ValueType other) const {
3232   switch (other) {
3233   case nullValue:
3234     return (isNumeric() && asDouble() == 0.0) ||
3235            (type_ == booleanValue && value_.bool_ == false) ||
3236            (type_ == stringValue && asString() == "") ||
3237            (type_ == arrayValue && value_.map_->size() == 0) ||
3238            (type_ == objectValue && value_.map_->size() == 0) ||
3239            type_ == nullValue;
3240   case intValue:
3241     return isInt() ||
3242            (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
3243            type_ == booleanValue || type_ == nullValue;
3244   case uintValue:
3245     return isUInt() ||
3246            (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
3247            type_ == booleanValue || type_ == nullValue;
3248   case realValue:
3249     return isNumeric() || type_ == booleanValue || type_ == nullValue;
3250   case booleanValue:
3251     return isNumeric() || type_ == booleanValue || type_ == nullValue;
3252   case stringValue:
3253     return isNumeric() || type_ == booleanValue || type_ == stringValue ||
3254            type_ == nullValue;
3255   case arrayValue:
3256     return type_ == arrayValue || type_ == nullValue;
3257   case objectValue:
3258     return type_ == objectValue || type_ == nullValue;
3259   }
3260   JSON_ASSERT_UNREACHABLE;
3261   return false;
3262 }
3263 
3264 /// Number of values in array or object
size() const3265 ArrayIndex Value::size() const {
3266   switch (type_) {
3267   case nullValue:
3268   case intValue:
3269   case uintValue:
3270   case realValue:
3271   case booleanValue:
3272   case stringValue:
3273     return 0;
3274   case arrayValue: // size of the array is highest index + 1
3275     if (!value_.map_->empty()) {
3276       ObjectValues::const_iterator itLast = value_.map_->end();
3277       --itLast;
3278       return (*itLast).first.index() + 1;
3279     }
3280     return 0;
3281   case objectValue:
3282     return ArrayIndex(value_.map_->size());
3283   }
3284   JSON_ASSERT_UNREACHABLE;
3285   return 0; // unreachable;
3286 }
3287 
empty() const3288 bool Value::empty() const {
3289   if (isNull() || isArray() || isObject())
3290     return size() == 0u;
3291   else
3292     return false;
3293 }
3294 
operator !() const3295 bool Value::operator!() const { return isNull(); }
3296 
clear()3297 void Value::clear() {
3298   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
3299                           type_ == objectValue,
3300                       "in Json::Value::clear(): requires complex value");
3301   start_ = 0;
3302   limit_ = 0;
3303   switch (type_) {
3304   case arrayValue:
3305   case objectValue:
3306     value_.map_->clear();
3307     break;
3308   default:
3309     break;
3310   }
3311 }
3312 
resize(ArrayIndex newSize)3313 void Value::resize(ArrayIndex newSize) {
3314   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3315                       "in Json::Value::resize(): requires arrayValue");
3316   if (type_ == nullValue)
3317     *this = Value(arrayValue);
3318   ArrayIndex oldSize = size();
3319   if (newSize == 0)
3320     clear();
3321   else if (newSize > oldSize)
3322     (*this)[newSize - 1];
3323   else {
3324     for (ArrayIndex index = newSize; index < oldSize; ++index) {
3325       value_.map_->erase(index);
3326     }
3327     assert(size() == newSize);
3328   }
3329 }
3330 
operator [](ArrayIndex index)3331 Value& Value::operator[](ArrayIndex index) {
3332   JSON_ASSERT_MESSAGE(
3333       type_ == nullValue || type_ == arrayValue,
3334       "in Json::Value::operator[](ArrayIndex): requires arrayValue");
3335   if (type_ == nullValue)
3336     *this = Value(arrayValue);
3337   CZString key(index);
3338   ObjectValues::iterator it = value_.map_->lower_bound(key);
3339   if (it != value_.map_->end() && (*it).first == key)
3340     return (*it).second;
3341 
3342   ObjectValues::value_type defaultValue(key, nullRef);
3343   it = value_.map_->insert(it, defaultValue);
3344   return (*it).second;
3345 }
3346 
operator [](int index)3347 Value& Value::operator[](int index) {
3348   JSON_ASSERT_MESSAGE(
3349       index >= 0,
3350       "in Json::Value::operator[](int index): index cannot be negative");
3351   return (*this)[ArrayIndex(index)];
3352 }
3353 
operator [](ArrayIndex index) const3354 const Value& Value::operator[](ArrayIndex index) const {
3355   JSON_ASSERT_MESSAGE(
3356       type_ == nullValue || type_ == arrayValue,
3357       "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
3358   if (type_ == nullValue)
3359     return nullRef;
3360   CZString key(index);
3361   ObjectValues::const_iterator it = value_.map_->find(key);
3362   if (it == value_.map_->end())
3363     return nullRef;
3364   return (*it).second;
3365 }
3366 
operator [](int index) const3367 const Value& Value::operator[](int index) const {
3368   JSON_ASSERT_MESSAGE(
3369       index >= 0,
3370       "in Json::Value::operator[](int index) const: index cannot be negative");
3371   return (*this)[ArrayIndex(index)];
3372 }
3373 
initBasic(ValueType vtype,bool allocated)3374 void Value::initBasic(ValueType vtype, bool allocated) {
3375   type_ = vtype;
3376   allocated_ = allocated;
3377   comments_ = 0;
3378   start_ = 0;
3379   limit_ = 0;
3380 }
3381 
3382 // Access an object value by name, create a null member if it does not exist.
3383 // @pre Type of '*this' is object or null.
3384 // @param key is null-terminated.
resolveReference(const char * key)3385 Value& Value::resolveReference(const char* key) {
3386   JSON_ASSERT_MESSAGE(
3387       type_ == nullValue || type_ == objectValue,
3388       "in Json::Value::resolveReference(): requires objectValue");
3389   if (type_ == nullValue)
3390     *this = Value(objectValue);
3391   CZString actualKey(
3392       key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
3393   ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3394   if (it != value_.map_->end() && (*it).first == actualKey)
3395     return (*it).second;
3396 
3397   ObjectValues::value_type defaultValue(actualKey, nullRef);
3398   it = value_.map_->insert(it, defaultValue);
3399   Value& value = (*it).second;
3400   return value;
3401 }
3402 
3403 // @param key is not null-terminated.
resolveReference(char const * key,char const * cend)3404 Value& Value::resolveReference(char const* key, char const* cend)
3405 {
3406   JSON_ASSERT_MESSAGE(
3407       type_ == nullValue || type_ == objectValue,
3408       "in Json::Value::resolveReference(key, end): requires objectValue");
3409   if (type_ == nullValue)
3410     *this = Value(objectValue);
3411   CZString actualKey(
3412       key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
3413   ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3414   if (it != value_.map_->end() && (*it).first == actualKey)
3415     return (*it).second;
3416 
3417   ObjectValues::value_type defaultValue(actualKey, nullRef);
3418   it = value_.map_->insert(it, defaultValue);
3419   Value& value = (*it).second;
3420   return value;
3421 }
3422 
get(ArrayIndex index,const Value & defaultValue) const3423 Value Value::get(ArrayIndex index, const Value& defaultValue) const {
3424   const Value* value = &((*this)[index]);
3425   return value == &nullRef ? defaultValue : *value;
3426 }
3427 
isValidIndex(ArrayIndex index) const3428 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
3429 
find(char const * key,char const * cend) const3430 Value const* Value::find(char const* key, char const* cend) const
3431 {
3432   JSON_ASSERT_MESSAGE(
3433       type_ == nullValue || type_ == objectValue,
3434       "in Json::Value::find(key, end, found): requires objectValue or nullValue");
3435   if (type_ == nullValue) return NULL;
3436   CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3437   ObjectValues::const_iterator it = value_.map_->find(actualKey);
3438   if (it == value_.map_->end()) return NULL;
3439   return &(*it).second;
3440 }
operator [](const char * key) const3441 const Value& Value::operator[](const char* key) const
3442 {
3443   Value const* found = find(key, key + strlen(key));
3444   if (!found) return nullRef;
3445   return *found;
3446 }
operator [](std::string const & key) const3447 Value const& Value::operator[](std::string const& key) const
3448 {
3449   Value const* found = find(key.data(), key.data() + key.length());
3450   if (!found) return nullRef;
3451   return *found;
3452 }
3453 
operator [](const char * key)3454 Value& Value::operator[](const char* key) {
3455   return resolveReference(key, key + strlen(key));
3456 }
3457 
operator [](const std::string & key)3458 Value& Value::operator[](const std::string& key) {
3459   return resolveReference(key.data(), key.data() + key.length());
3460 }
3461 
operator [](const StaticString & key)3462 Value& Value::operator[](const StaticString& key) {
3463   return resolveReference(key.c_str());
3464 }
3465 
3466 #ifdef JSON_USE_CPPTL
operator [](const CppTL::ConstString & key)3467 Value& Value::operator[](const CppTL::ConstString& key) {
3468   return resolveReference(key.c_str(), key.end_c_str());
3469 }
operator [](CppTL::ConstString const & key) const3470 Value const& Value::operator[](CppTL::ConstString const& key) const
3471 {
3472   Value const* found = find(key.c_str(), key.end_c_str());
3473   if (!found) return nullRef;
3474   return *found;
3475 }
3476 #endif
3477 
append(const Value & value)3478 Value& Value::append(const Value& value) { return (*this)[size()] = value; }
3479 
get(char const * key,char const * cend,Value const & defaultValue) const3480 Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
3481 {
3482   Value const* found = find(key, cend);
3483   return !found ? defaultValue : *found;
3484 }
get(char const * key,Value const & defaultValue) const3485 Value Value::get(char const* key, Value const& defaultValue) const
3486 {
3487   return get(key, key + strlen(key), defaultValue);
3488 }
get(std::string const & key,Value const & defaultValue) const3489 Value Value::get(std::string const& key, Value const& defaultValue) const
3490 {
3491   return get(key.data(), key.data() + key.length(), defaultValue);
3492 }
3493 
3494 
removeMember(const char * key,const char * cend,Value * removed)3495 bool Value::removeMember(const char* key, const char* cend, Value* removed)
3496 {
3497   if (type_ != objectValue) {
3498     return false;
3499   }
3500   CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
3501   ObjectValues::iterator it = value_.map_->find(actualKey);
3502   if (it == value_.map_->end())
3503     return false;
3504   *removed = it->second;
3505   value_.map_->erase(it);
3506   return true;
3507 }
removeMember(const char * key,Value * removed)3508 bool Value::removeMember(const char* key, Value* removed)
3509 {
3510   return removeMember(key, key + strlen(key), removed);
3511 }
removeMember(std::string const & key,Value * removed)3512 bool Value::removeMember(std::string const& key, Value* removed)
3513 {
3514   return removeMember(key.data(), key.data() + key.length(), removed);
3515 }
removeMember(const char * key)3516 Value Value::removeMember(const char* key)
3517 {
3518   JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3519                       "in Json::Value::removeMember(): requires objectValue");
3520   if (type_ == nullValue)
3521     return nullRef;
3522 
3523   Value removed;  // null
3524   removeMember(key, key + strlen(key), &removed);
3525   return removed; // still null if removeMember() did nothing
3526 }
removeMember(const std::string & key)3527 Value Value::removeMember(const std::string& key)
3528 {
3529   return removeMember(key.c_str());
3530 }
3531 
removeIndex(ArrayIndex index,Value * removed)3532 bool Value::removeIndex(ArrayIndex index, Value* removed) {
3533   if (type_ != arrayValue) {
3534     return false;
3535   }
3536   CZString key(index);
3537   ObjectValues::iterator it = value_.map_->find(key);
3538   if (it == value_.map_->end()) {
3539     return false;
3540   }
3541   *removed = it->second;
3542   ArrayIndex oldSize = size();
3543   // shift left all items left, into the place of the "removed"
3544   for (ArrayIndex i = index; i < (oldSize - 1); ++i){
3545     CZString keey(i);
3546     (*value_.map_)[keey] = (*this)[i + 1];
3547   }
3548   // erase the last one ("leftover")
3549   CZString keyLast(oldSize - 1);
3550   ObjectValues::iterator itLast = value_.map_->find(keyLast);
3551   value_.map_->erase(itLast);
3552   return true;
3553 }
3554 
3555 #ifdef JSON_USE_CPPTL
get(const CppTL::ConstString & key,const Value & defaultValue) const3556 Value Value::get(const CppTL::ConstString& key,
3557                  const Value& defaultValue) const {
3558   return get(key.c_str(), key.end_c_str(), defaultValue);
3559 }
3560 #endif
3561 
isMember(char const * key,char const * cend) const3562 bool Value::isMember(char const* key, char const* cend) const
3563 {
3564   Value const* value = find(key, cend);
3565   return NULL != value;
3566 }
isMember(char const * key) const3567 bool Value::isMember(char const* key) const
3568 {
3569   return isMember(key, key + strlen(key));
3570 }
isMember(std::string const & key) const3571 bool Value::isMember(std::string const& key) const
3572 {
3573   return isMember(key.data(), key.data() + key.length());
3574 }
3575 
3576 #ifdef JSON_USE_CPPTL
isMember(const CppTL::ConstString & key) const3577 bool Value::isMember(const CppTL::ConstString& key) const {
3578   return isMember(key.c_str(), key.end_c_str());
3579 }
3580 #endif
3581 
getMemberNames() const3582 Value::Members Value::getMemberNames() const {
3583   JSON_ASSERT_MESSAGE(
3584       type_ == nullValue || type_ == objectValue,
3585       "in Json::Value::getMemberNames(), value must be objectValue");
3586   if (type_ == nullValue)
3587     return Value::Members();
3588   Members members;
3589   members.reserve(value_.map_->size());
3590   ObjectValues::const_iterator it = value_.map_->begin();
3591   ObjectValues::const_iterator itEnd = value_.map_->end();
3592   for (; it != itEnd; ++it) {
3593     members.push_back(std::string((*it).first.data(),
3594                                   (*it).first.length()));
3595   }
3596   return members;
3597 }
3598 //
3599 //# ifdef JSON_USE_CPPTL
3600 // EnumMemberNames
3601 // Value::enumMemberNames() const
3602 //{
3603 //   if ( type_ == objectValue )
3604 //   {
3605 //      return CppTL::Enum::any(  CppTL::Enum::transform(
3606 //         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
3607 //         MemberNamesTransform() ) );
3608 //   }
3609 //   return EnumMemberNames();
3610 //}
3611 //
3612 //
3613 // EnumValues
3614 // Value::enumValues() const
3615 //{
3616 //   if ( type_ == objectValue  ||  type_ == arrayValue )
3617 //      return CppTL::Enum::anyValues( *(value_.map_),
3618 //                                     CppTL::Type<const Value &>() );
3619 //   return EnumValues();
3620 //}
3621 //
3622 //# endif
3623 
IsIntegral(double d)3624 static bool IsIntegral(double d) {
3625   double integral_part;
3626   return modf(d, &integral_part) == 0.0;
3627 }
3628 
isNull() const3629 bool Value::isNull() const { return type_ == nullValue; }
3630 
isBool() const3631 bool Value::isBool() const { return type_ == booleanValue; }
3632 
isInt() const3633 bool Value::isInt() const {
3634   switch (type_) {
3635   case intValue:
3636     return value_.int_ >= minInt && value_.int_ <= maxInt;
3637   case uintValue:
3638     return value_.uint_ <= UInt(maxInt);
3639   case realValue:
3640     return value_.real_ >= minInt && value_.real_ <= maxInt &&
3641            IsIntegral(value_.real_);
3642   default:
3643     break;
3644   }
3645   return false;
3646 }
3647 
isUInt() const3648 bool Value::isUInt() const {
3649   switch (type_) {
3650   case intValue:
3651     return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
3652   case uintValue:
3653     return value_.uint_ <= maxUInt;
3654   case realValue:
3655     return value_.real_ >= 0 && value_.real_ <= maxUInt &&
3656            IsIntegral(value_.real_);
3657   default:
3658     break;
3659   }
3660   return false;
3661 }
3662 
isInt64() const3663 bool Value::isInt64() const {
3664 #if defined(JSON_HAS_INT64)
3665   switch (type_) {
3666   case intValue:
3667     return true;
3668   case uintValue:
3669     return value_.uint_ <= UInt64(maxInt64);
3670   case realValue:
3671     // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
3672     // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
3673     // require the value to be strictly less than the limit.
3674     return value_.real_ >= double(minInt64) &&
3675            value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
3676   default:
3677     break;
3678   }
3679 #endif // JSON_HAS_INT64
3680   return false;
3681 }
3682 
isUInt64() const3683 bool Value::isUInt64() const {
3684 #if defined(JSON_HAS_INT64)
3685   switch (type_) {
3686   case intValue:
3687     return value_.int_ >= 0;
3688   case uintValue:
3689     return true;
3690   case realValue:
3691     // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3692     // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3693     // require the value to be strictly less than the limit.
3694     return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
3695            IsIntegral(value_.real_);
3696   default:
3697     break;
3698   }
3699 #endif // JSON_HAS_INT64
3700   return false;
3701 }
3702 
isIntegral() const3703 bool Value::isIntegral() const {
3704 #if defined(JSON_HAS_INT64)
3705   return isInt64() || isUInt64();
3706 #else
3707   return isInt() || isUInt();
3708 #endif
3709 }
3710 
isDouble() const3711 bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
3712 
isNumeric() const3713 bool Value::isNumeric() const { return isIntegral() || isDouble(); }
3714 
isString() const3715 bool Value::isString() const { return type_ == stringValue; }
3716 
isArray() const3717 bool Value::isArray() const { return type_ == arrayValue; }
3718 
isObject() const3719 bool Value::isObject() const { return type_ == objectValue; }
3720 
setComment(const char * comment,size_t len,CommentPlacement placement)3721 void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
3722   if (!comments_)
3723     comments_ = new CommentInfo[numberOfCommentPlacement];
3724   if ((len > 0) && (comment[len-1] == '\n')) {
3725     // Always discard trailing newline, to aid indentation.
3726     len -= 1;
3727   }
3728   comments_[placement].setComment(comment, len);
3729 }
3730 
setComment(const char * comment,CommentPlacement placement)3731 void Value::setComment(const char* comment, CommentPlacement placement) {
3732   setComment(comment, strlen(comment), placement);
3733 }
3734 
setComment(const std::string & comment,CommentPlacement placement)3735 void Value::setComment(const std::string& comment, CommentPlacement placement) {
3736   setComment(comment.c_str(), comment.length(), placement);
3737 }
3738 
hasComment(CommentPlacement placement) const3739 bool Value::hasComment(CommentPlacement placement) const {
3740   return comments_ != 0 && comments_[placement].comment_ != 0;
3741 }
3742 
getComment(CommentPlacement placement) const3743 std::string Value::getComment(CommentPlacement placement) const {
3744   if (hasComment(placement))
3745     return comments_[placement].comment_;
3746   return "";
3747 }
3748 
setOffsetStart(size_t start)3749 void Value::setOffsetStart(size_t start) { start_ = start; }
3750 
setOffsetLimit(size_t limit)3751 void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
3752 
getOffsetStart() const3753 size_t Value::getOffsetStart() const { return start_; }
3754 
getOffsetLimit() const3755 size_t Value::getOffsetLimit() const { return limit_; }
3756 
toStyledString() const3757 std::string Value::toStyledString() const {
3758   StyledWriter writer;
3759   return writer.write(*this);
3760 }
3761 
begin() const3762 Value::const_iterator Value::begin() const {
3763   switch (type_) {
3764   case arrayValue:
3765   case objectValue:
3766     if (value_.map_)
3767       return const_iterator(value_.map_->begin());
3768     break;
3769   default:
3770     break;
3771   }
3772   return const_iterator();
3773 }
3774 
end() const3775 Value::const_iterator Value::end() const {
3776   switch (type_) {
3777   case arrayValue:
3778   case objectValue:
3779     if (value_.map_)
3780       return const_iterator(value_.map_->end());
3781     break;
3782   default:
3783     break;
3784   }
3785   return const_iterator();
3786 }
3787 
begin()3788 Value::iterator Value::begin() {
3789   switch (type_) {
3790   case arrayValue:
3791   case objectValue:
3792     if (value_.map_)
3793       return iterator(value_.map_->begin());
3794     break;
3795   default:
3796     break;
3797   }
3798   return iterator();
3799 }
3800 
end()3801 Value::iterator Value::end() {
3802   switch (type_) {
3803   case arrayValue:
3804   case objectValue:
3805     if (value_.map_)
3806       return iterator(value_.map_->end());
3807     break;
3808   default:
3809     break;
3810   }
3811   return iterator();
3812 }
3813 
3814 // class PathArgument
3815 // //////////////////////////////////////////////////////////////////
3816 
PathArgument()3817 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
3818 
PathArgument(ArrayIndex index)3819 PathArgument::PathArgument(ArrayIndex index)
3820     : key_(), index_(index), kind_(kindIndex) {}
3821 
PathArgument(const char * key)3822 PathArgument::PathArgument(const char* key)
3823     : key_(key), index_(), kind_(kindKey) {}
3824 
PathArgument(const std::string & key)3825 PathArgument::PathArgument(const std::string& key)
3826     : key_(key.c_str()), index_(), kind_(kindKey) {}
3827 
3828 // class Path
3829 // //////////////////////////////////////////////////////////////////
3830 
Path(const std::string & path,const PathArgument & a1,const PathArgument & a2,const PathArgument & a3,const PathArgument & a4,const PathArgument & a5)3831 Path::Path(const std::string& path,
3832            const PathArgument& a1,
3833            const PathArgument& a2,
3834            const PathArgument& a3,
3835            const PathArgument& a4,
3836            const PathArgument& a5) {
3837   InArgs in;
3838   in.push_back(&a1);
3839   in.push_back(&a2);
3840   in.push_back(&a3);
3841   in.push_back(&a4);
3842   in.push_back(&a5);
3843   makePath(path, in);
3844 }
3845 
makePath(const std::string & path,const InArgs & in)3846 void Path::makePath(const std::string& path, const InArgs& in) {
3847   const char* current = path.c_str();
3848   const char* end = current + path.length();
3849   InArgs::const_iterator itInArg = in.begin();
3850   while (current != end) {
3851     if (*current == '[') {
3852       ++current;
3853       if (*current == '%')
3854         addPathInArg(path, in, itInArg, PathArgument::kindIndex);
3855       else {
3856         ArrayIndex index = 0;
3857         for (; current != end && *current >= '0' && *current <= '9'; ++current)
3858           index = index * 10 + ArrayIndex(*current - '0');
3859         args_.push_back(index);
3860       }
3861       if (current == end || *current++ != ']')
3862         invalidPath(path, int(current - path.c_str()));
3863     } else if (*current == '%') {
3864       addPathInArg(path, in, itInArg, PathArgument::kindKey);
3865       ++current;
3866     } else if (*current == '.') {
3867       ++current;
3868     } else {
3869       const char* beginName = current;
3870       while (current != end && !strchr("[.", *current))
3871         ++current;
3872       args_.push_back(std::string(beginName, current));
3873     }
3874   }
3875 }
3876 
addPathInArg(const std::string &,const InArgs & in,InArgs::const_iterator & itInArg,PathArgument::Kind kind)3877 void Path::addPathInArg(const std::string& /*path*/,
3878                         const InArgs& in,
3879                         InArgs::const_iterator& itInArg,
3880                         PathArgument::Kind kind) {
3881   if (itInArg == in.end()) {
3882     // Error: missing argument %d
3883   } else if ((*itInArg)->kind_ != kind) {
3884     // Error: bad argument type
3885   } else {
3886     args_.push_back(**itInArg);
3887   }
3888 }
3889 
invalidPath(const std::string &,int)3890 void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
3891   // Error: invalid path.
3892 }
3893 
resolve(const Value & root) const3894 const Value& Path::resolve(const Value& root) const {
3895   const Value* node = &root;
3896   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
3897     const PathArgument& arg = *it;
3898     if (arg.kind_ == PathArgument::kindIndex) {
3899       if (!node->isArray() || !node->isValidIndex(arg.index_)) {
3900         // Error: unable to resolve path (array value expected at position...
3901       }
3902       node = &((*node)[arg.index_]);
3903     } else if (arg.kind_ == PathArgument::kindKey) {
3904       if (!node->isObject()) {
3905         // Error: unable to resolve path (object value expected at position...)
3906       }
3907       node = &((*node)[arg.key_]);
3908       if (node == &Value::nullRef) {
3909         // Error: unable to resolve path (object has no member named '' at
3910         // position...)
3911       }
3912     }
3913   }
3914   return *node;
3915 }
3916 
resolve(const Value & root,const Value & defaultValue) const3917 Value Path::resolve(const Value& root, const Value& defaultValue) const {
3918   const Value* node = &root;
3919   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
3920     const PathArgument& arg = *it;
3921     if (arg.kind_ == PathArgument::kindIndex) {
3922       if (!node->isArray() || !node->isValidIndex(arg.index_))
3923         return defaultValue;
3924       node = &((*node)[arg.index_]);
3925     } else if (arg.kind_ == PathArgument::kindKey) {
3926       if (!node->isObject())
3927         return defaultValue;
3928       node = &((*node)[arg.key_]);
3929       if (node == &Value::nullRef)
3930         return defaultValue;
3931     }
3932   }
3933   return *node;
3934 }
3935 
make(Value & root) const3936 Value& Path::make(Value& root) const {
3937   Value* node = &root;
3938   for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
3939     const PathArgument& arg = *it;
3940     if (arg.kind_ == PathArgument::kindIndex) {
3941       if (!node->isArray()) {
3942         // Error: node is not an array at position ...
3943       }
3944       node = &((*node)[arg.index_]);
3945     } else if (arg.kind_ == PathArgument::kindKey) {
3946       if (!node->isObject()) {
3947         // Error: node is not an object at position...
3948       }
3949       node = &((*node)[arg.key_]);
3950     }
3951   }
3952   return *node;
3953 }
3954 
3955 } // namespace Json
3956 
3957 // //////////////////////////////////////////////////////////////////////
3958 // End of content of file: src/lib_json/json_value.cpp
3959 // //////////////////////////////////////////////////////////////////////
3960 
3961 
3962 
3963 
3964 
3965 
3966 // //////////////////////////////////////////////////////////////////////
3967 // Beginning of content of file: src/lib_json/json_writer.cpp
3968 // //////////////////////////////////////////////////////////////////////
3969 
3970 // Copyright 2011 Baptiste Lepilleur
3971 // Distributed under MIT license, or public domain if desired and
3972 // recognized in your jurisdiction.
3973 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
3974 
3975 #if !defined(JSON_IS_AMALGAMATION)
3976 #include <json/writer.h>
3977 #include "json_tool.h"
3978 #endif // if !defined(JSON_IS_AMALGAMATION)
3979 #include <iomanip>
3980 #include <memory>
3981 #include <sstream>
3982 #include <utility>
3983 #include <set>
3984 #include <cassert>
3985 #include <cstring>
3986 #include <cstdio>
3987 
3988 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
3989 #include <float.h>
3990 #define isfinite _finite
3991 #elif defined(__sun) && defined(__SVR4) //Solaris
3992 #if !defined(isfinite)
3993 #include <ieeefp.h>
3994 #define isfinite finite
3995 #endif
3996 #elif defined(_AIX)
3997 #if !defined(isfinite)
3998 #include <math.h>
3999 #define isfinite finite
4000 #endif
4001 #elif defined(__hpux)
4002 #if !defined(isfinite)
4003 #if defined(__ia64) && !defined(finite)
4004 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \
4005                      _Isfinitef(x) : _IsFinite(x)))
4006 #else
4007 #include <math.h>
4008 #define isfinite finite
4009 #endif
4010 #endif
4011 #else
4012 #include <cmath>
4013 #if !(defined(__QNXNTO__)) // QNX already defines isfinite
4014 #define isfinite std::isfinite
4015 #endif
4016 #endif
4017 
4018 #if defined(_MSC_VER)
4019 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
4020 #define snprintf sprintf_s
4021 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
4022 #define snprintf std::snprintf
4023 #else
4024 #define snprintf _snprintf
4025 #endif
4026 #elif defined(__ANDROID__) || defined(__QNXNTO__)
4027 #define snprintf snprintf
4028 #elif __cplusplus >= 201103L
4029 #define snprintf std::snprintf
4030 #endif
4031 
4032 #if defined(__BORLANDC__)
4033 #include <float.h>
4034 #define isfinite _finite
4035 #define snprintf _snprintf
4036 #endif
4037 
4038 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
4039 // Disable warning about strdup being deprecated.
4040 #pragma warning(disable : 4996)
4041 #endif
4042 
4043 namespace Json {
4044 
4045 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
4046 typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
4047 #else
4048 typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
4049 #endif
4050 
containsControlCharacter(const char * str)4051 static bool containsControlCharacter(const char* str) {
4052   while (*str) {
4053     if (isControlCharacter(*(str++)))
4054       return true;
4055   }
4056   return false;
4057 }
4058 
containsControlCharacter0(const char * str,unsigned len)4059 static bool containsControlCharacter0(const char* str, unsigned len) {
4060   char const* end = str + len;
4061   while (end != str) {
4062     if (isControlCharacter(*str) || 0==*str)
4063       return true;
4064     ++str;
4065   }
4066   return false;
4067 }
4068 
valueToString(LargestInt value)4069 std::string valueToString(LargestInt value) {
4070   UIntToStringBuffer buffer;
4071   char* current = buffer + sizeof(buffer);
4072   if (value == Value::minLargestInt) {
4073     uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
4074     *--current = '-';
4075   } else if (value < 0) {
4076     uintToString(LargestUInt(-value), current);
4077     *--current = '-';
4078   } else {
4079     uintToString(LargestUInt(value), current);
4080   }
4081   assert(current >= buffer);
4082   return current;
4083 }
4084 
valueToString(LargestUInt value)4085 std::string valueToString(LargestUInt value) {
4086   UIntToStringBuffer buffer;
4087   char* current = buffer + sizeof(buffer);
4088   uintToString(value, current);
4089   assert(current >= buffer);
4090   return current;
4091 }
4092 
4093 #if defined(JSON_HAS_INT64)
4094 
valueToString(Int value)4095 std::string valueToString(Int value) {
4096   return valueToString(LargestInt(value));
4097 }
4098 
valueToString(UInt value)4099 std::string valueToString(UInt value) {
4100   return valueToString(LargestUInt(value));
4101 }
4102 
4103 #endif // # if defined(JSON_HAS_INT64)
4104 
valueToString(double value,bool useSpecialFloats,unsigned int precision)4105 std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) {
4106   // Allocate a buffer that is more than large enough to store the 16 digits of
4107   // precision requested below.
4108   char buffer[32];
4109   int len = -1;
4110 
4111   char formatString[6];
4112   sprintf(formatString, "%%.%dg", precision);
4113 
4114   // Print into the buffer. We need not request the alternative representation
4115   // that always has a decimal point because JSON doesn't distingish the
4116   // concepts of reals and integers.
4117   if (isfinite(value)) {
4118     len = snprintf(buffer, sizeof(buffer), formatString, value);
4119   } else {
4120     // IEEE standard states that NaN values will not compare to themselves
4121     if (value != value) {
4122       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
4123     } else if (value < 0) {
4124       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
4125     } else {
4126       len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
4127     }
4128     // For those, we do not need to call fixNumLoc, but it is fast.
4129   }
4130   assert(len >= 0);
4131   fixNumericLocale(buffer, buffer + len);
4132   return buffer;
4133 }
4134 
valueToString(double value)4135 std::string valueToString(double value) { return valueToString(value, false, 17); }
4136 
valueToString(bool value)4137 std::string valueToString(bool value) { return value ? "true" : "false"; }
4138 
valueToQuotedString(const char * value)4139 std::string valueToQuotedString(const char* value) {
4140   if (value == NULL)
4141     return "";
4142   // Not sure how to handle unicode...
4143   if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
4144       !containsControlCharacter(value))
4145     return std::string("\"") + value + "\"";
4146   // We have to walk value and escape any special characters.
4147   // Appending to std::string is not efficient, but this should be rare.
4148   // (Note: forward slashes are *not* rare, but I am not escaping them.)
4149   std::string::size_type maxsize =
4150       strlen(value) * 2 + 3; // allescaped+quotes+NULL
4151   std::string result;
4152   result.reserve(maxsize); // to avoid lots of mallocs
4153   result += "\"";
4154   for (const char* c = value; *c != 0; ++c) {
4155     switch (*c) {
4156     case '\"':
4157       result += "\\\"";
4158       break;
4159     case '\\':
4160       result += "\\\\";
4161       break;
4162     case '\b':
4163       result += "\\b";
4164       break;
4165     case '\f':
4166       result += "\\f";
4167       break;
4168     case '\n':
4169       result += "\\n";
4170       break;
4171     case '\r':
4172       result += "\\r";
4173       break;
4174     case '\t':
4175       result += "\\t";
4176       break;
4177     // case '/':
4178     // Even though \/ is considered a legal escape in JSON, a bare
4179     // slash is also legal, so I see no reason to escape it.
4180     // (I hope I am not misunderstanding something.
4181     // blep notes: actually escaping \/ may be useful in javascript to avoid </
4182     // sequence.
4183     // Should add a flag to allow this compatibility mode and prevent this
4184     // sequence from occurring.
4185     default:
4186       if (isControlCharacter(*c)) {
4187         std::ostringstream oss;
4188         oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
4189             << std::setw(4) << static_cast<int>(*c);
4190         result += oss.str();
4191       } else {
4192         result += *c;
4193       }
4194       break;
4195     }
4196   }
4197   result += "\"";
4198   return result;
4199 }
4200 
4201 // https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
strnpbrk(char const * s,char const * accept,size_t n)4202 static char const* strnpbrk(char const* s, char const* accept, size_t n) {
4203   assert((s || !n) && accept);
4204 
4205   char const* const end = s + n;
4206   for (char const* cur = s; cur < end; ++cur) {
4207     int const c = *cur;
4208     for (char const* a = accept; *a; ++a) {
4209       if (*a == c) {
4210         return cur;
4211       }
4212     }
4213   }
4214   return NULL;
4215 }
valueToQuotedStringN(const char * value,unsigned length)4216 static std::string valueToQuotedStringN(const char* value, unsigned length) {
4217   if (value == NULL)
4218     return "";
4219   // Not sure how to handle unicode...
4220   if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
4221       !containsControlCharacter0(value, length))
4222     return std::string("\"") + value + "\"";
4223   // We have to walk value and escape any special characters.
4224   // Appending to std::string is not efficient, but this should be rare.
4225   // (Note: forward slashes are *not* rare, but I am not escaping them.)
4226   std::string::size_type maxsize =
4227       length * 2 + 3; // allescaped+quotes+NULL
4228   std::string result;
4229   result.reserve(maxsize); // to avoid lots of mallocs
4230   result += "\"";
4231   char const* end = value + length;
4232   for (const char* c = value; c != end; ++c) {
4233     switch (*c) {
4234     case '\"':
4235       result += "\\\"";
4236       break;
4237     case '\\':
4238       result += "\\\\";
4239       break;
4240     case '\b':
4241       result += "\\b";
4242       break;
4243     case '\f':
4244       result += "\\f";
4245       break;
4246     case '\n':
4247       result += "\\n";
4248       break;
4249     case '\r':
4250       result += "\\r";
4251       break;
4252     case '\t':
4253       result += "\\t";
4254       break;
4255     // case '/':
4256     // Even though \/ is considered a legal escape in JSON, a bare
4257     // slash is also legal, so I see no reason to escape it.
4258     // (I hope I am not misunderstanding something.)
4259     // blep notes: actually escaping \/ may be useful in javascript to avoid </
4260     // sequence.
4261     // Should add a flag to allow this compatibility mode and prevent this
4262     // sequence from occurring.
4263     default:
4264       if ((isControlCharacter(*c)) || (*c == 0)) {
4265         std::ostringstream oss;
4266         oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
4267             << std::setw(4) << static_cast<int>(*c);
4268         result += oss.str();
4269       } else {
4270         result += *c;
4271       }
4272       break;
4273     }
4274   }
4275   result += "\"";
4276   return result;
4277 }
4278 
4279 // Class Writer
4280 // //////////////////////////////////////////////////////////////////
~Writer()4281 Writer::~Writer() {}
4282 
4283 // Class FastWriter
4284 // //////////////////////////////////////////////////////////////////
4285 
FastWriter()4286 FastWriter::FastWriter()
4287     : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
4288       omitEndingLineFeed_(false) {}
4289 
enableYAMLCompatibility()4290 void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
4291 
dropNullPlaceholders()4292 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
4293 
omitEndingLineFeed()4294 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
4295 
write(const Value & root)4296 std::string FastWriter::write(const Value& root) {
4297   document_ = "";
4298   writeValue(root);
4299   if (!omitEndingLineFeed_)
4300     document_ += "\n";
4301   return document_;
4302 }
4303 
writeValue(const Value & value)4304 void FastWriter::writeValue(const Value& value) {
4305   switch (value.type()) {
4306   case nullValue:
4307     if (!dropNullPlaceholders_)
4308       document_ += "null";
4309     break;
4310   case intValue:
4311     document_ += valueToString(value.asLargestInt());
4312     break;
4313   case uintValue:
4314     document_ += valueToString(value.asLargestUInt());
4315     break;
4316   case realValue:
4317     document_ += valueToString(value.asDouble());
4318     break;
4319   case stringValue:
4320   {
4321     // Is NULL possible for value.string_?
4322     char const* str;
4323     char const* end;
4324     bool ok = value.getString(&str, &end);
4325     if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
4326     break;
4327   }
4328   case booleanValue:
4329     document_ += valueToString(value.asBool());
4330     break;
4331   case arrayValue: {
4332     document_ += '[';
4333     int size = value.size();
4334     for (int index = 0; index < size; ++index) {
4335       if (index > 0)
4336         document_ += ',';
4337       writeValue(value[index]);
4338     }
4339     document_ += ']';
4340   } break;
4341   case objectValue: {
4342     Value::Members members(value.getMemberNames());
4343     document_ += '{';
4344     for (Value::Members::iterator it = members.begin(); it != members.end();
4345          ++it) {
4346       const std::string& name = *it;
4347       if (it != members.begin())
4348         document_ += ',';
4349       document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
4350       document_ += yamlCompatiblityEnabled_ ? ": " : ":";
4351       writeValue(value[name]);
4352     }
4353     document_ += '}';
4354   } break;
4355   }
4356 }
4357 
4358 // Class StyledWriter
4359 // //////////////////////////////////////////////////////////////////
4360 
StyledWriter()4361 StyledWriter::StyledWriter()
4362     : rightMargin_(74), indentSize_(3), addChildValues_() {}
4363 
write(const Value & root)4364 std::string StyledWriter::write(const Value& root) {
4365   document_ = "";
4366   addChildValues_ = false;
4367   indentString_ = "";
4368   writeCommentBeforeValue(root);
4369   writeValue(root);
4370   writeCommentAfterValueOnSameLine(root);
4371   document_ += "\n";
4372   return document_;
4373 }
4374 
writeValue(const Value & value)4375 void StyledWriter::writeValue(const Value& value) {
4376   switch (value.type()) {
4377   case nullValue:
4378     pushValue("null");
4379     break;
4380   case intValue:
4381     pushValue(valueToString(value.asLargestInt()));
4382     break;
4383   case uintValue:
4384     pushValue(valueToString(value.asLargestUInt()));
4385     break;
4386   case realValue:
4387     pushValue(valueToString(value.asDouble()));
4388     break;
4389   case stringValue:
4390   {
4391     // Is NULL possible for value.string_?
4392     char const* str;
4393     char const* end;
4394     bool ok = value.getString(&str, &end);
4395     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4396     else pushValue("");
4397     break;
4398   }
4399   case booleanValue:
4400     pushValue(valueToString(value.asBool()));
4401     break;
4402   case arrayValue:
4403     writeArrayValue(value);
4404     break;
4405   case objectValue: {
4406     Value::Members members(value.getMemberNames());
4407     if (members.empty())
4408       pushValue("{}");
4409     else {
4410       writeWithIndent("{");
4411       indent();
4412       Value::Members::iterator it = members.begin();
4413       for (;;) {
4414         const std::string& name = *it;
4415         const Value& childValue = value[name];
4416         writeCommentBeforeValue(childValue);
4417         writeWithIndent(valueToQuotedString(name.c_str()));
4418         document_ += " : ";
4419         writeValue(childValue);
4420         if (++it == members.end()) {
4421           writeCommentAfterValueOnSameLine(childValue);
4422           break;
4423         }
4424         document_ += ',';
4425         writeCommentAfterValueOnSameLine(childValue);
4426       }
4427       unindent();
4428       writeWithIndent("}");
4429     }
4430   } break;
4431   }
4432 }
4433 
writeArrayValue(const Value & value)4434 void StyledWriter::writeArrayValue(const Value& value) {
4435   unsigned size = value.size();
4436   if (size == 0)
4437     pushValue("[]");
4438   else {
4439     bool isArrayMultiLine = isMultineArray(value);
4440     if (isArrayMultiLine) {
4441       writeWithIndent("[");
4442       indent();
4443       bool hasChildValue = !childValues_.empty();
4444       unsigned index = 0;
4445       for (;;) {
4446         const Value& childValue = value[index];
4447         writeCommentBeforeValue(childValue);
4448         if (hasChildValue)
4449           writeWithIndent(childValues_[index]);
4450         else {
4451           writeIndent();
4452           writeValue(childValue);
4453         }
4454         if (++index == size) {
4455           writeCommentAfterValueOnSameLine(childValue);
4456           break;
4457         }
4458         document_ += ',';
4459         writeCommentAfterValueOnSameLine(childValue);
4460       }
4461       unindent();
4462       writeWithIndent("]");
4463     } else // output on a single line
4464     {
4465       assert(childValues_.size() == size);
4466       document_ += "[ ";
4467       for (unsigned index = 0; index < size; ++index) {
4468         if (index > 0)
4469           document_ += ", ";
4470         document_ += childValues_[index];
4471       }
4472       document_ += " ]";
4473     }
4474   }
4475 }
4476 
isMultineArray(const Value & value)4477 bool StyledWriter::isMultineArray(const Value& value) {
4478   int size = value.size();
4479   bool isMultiLine = size * 3 >= rightMargin_;
4480   childValues_.clear();
4481   for (int index = 0; index < size && !isMultiLine; ++index) {
4482     const Value& childValue = value[index];
4483     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4484                         childValue.size() > 0);
4485   }
4486   if (!isMultiLine) // check if line length > max line length
4487   {
4488     childValues_.reserve(size);
4489     addChildValues_ = true;
4490     int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4491     for (int index = 0; index < size; ++index) {
4492       if (hasCommentForValue(value[index])) {
4493         isMultiLine = true;
4494       }
4495       writeValue(value[index]);
4496       lineLength += int(childValues_[index].length());
4497     }
4498     addChildValues_ = false;
4499     isMultiLine = isMultiLine || lineLength >= rightMargin_;
4500   }
4501   return isMultiLine;
4502 }
4503 
pushValue(const std::string & value)4504 void StyledWriter::pushValue(const std::string& value) {
4505   if (addChildValues_)
4506     childValues_.push_back(value);
4507   else
4508     document_ += value;
4509 }
4510 
writeIndent()4511 void StyledWriter::writeIndent() {
4512   if (!document_.empty()) {
4513     char last = document_[document_.length() - 1];
4514     if (last == ' ') // already indented
4515       return;
4516     if (last != '\n') // Comments may add new-line
4517       document_ += '\n';
4518   }
4519   document_ += indentString_;
4520 }
4521 
writeWithIndent(const std::string & value)4522 void StyledWriter::writeWithIndent(const std::string& value) {
4523   writeIndent();
4524   document_ += value;
4525 }
4526 
indent()4527 void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
4528 
unindent()4529 void StyledWriter::unindent() {
4530   assert(int(indentString_.size()) >= indentSize_);
4531   indentString_.resize(indentString_.size() - indentSize_);
4532 }
4533 
writeCommentBeforeValue(const Value & root)4534 void StyledWriter::writeCommentBeforeValue(const Value& root) {
4535   if (!root.hasComment(commentBefore))
4536     return;
4537 
4538   document_ += "\n";
4539   writeIndent();
4540   const std::string& comment = root.getComment(commentBefore);
4541   std::string::const_iterator iter = comment.begin();
4542   while (iter != comment.end()) {
4543     document_ += *iter;
4544     if (*iter == '\n' &&
4545        (iter != comment.end() && *(iter + 1) == '/'))
4546       writeIndent();
4547     ++iter;
4548   }
4549 
4550   // Comments are stripped of trailing newlines, so add one here
4551   document_ += "\n";
4552 }
4553 
writeCommentAfterValueOnSameLine(const Value & root)4554 void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
4555   if (root.hasComment(commentAfterOnSameLine))
4556     document_ += " " + root.getComment(commentAfterOnSameLine);
4557 
4558   if (root.hasComment(commentAfter)) {
4559     document_ += "\n";
4560     document_ += root.getComment(commentAfter);
4561     document_ += "\n";
4562   }
4563 }
4564 
hasCommentForValue(const Value & value)4565 bool StyledWriter::hasCommentForValue(const Value& value) {
4566   return value.hasComment(commentBefore) ||
4567          value.hasComment(commentAfterOnSameLine) ||
4568          value.hasComment(commentAfter);
4569 }
4570 
4571 // Class StyledStreamWriter
4572 // //////////////////////////////////////////////////////////////////
4573 
StyledStreamWriter(std::string indentation)4574 StyledStreamWriter::StyledStreamWriter(std::string indentation)
4575     : document_(NULL), rightMargin_(74), indentation_(indentation),
4576       addChildValues_() {}
4577 
write(std::ostream & out,const Value & root)4578 void StyledStreamWriter::write(std::ostream& out, const Value& root) {
4579   document_ = &out;
4580   addChildValues_ = false;
4581   indentString_ = "";
4582   indented_ = true;
4583   writeCommentBeforeValue(root);
4584   if (!indented_) writeIndent();
4585   indented_ = true;
4586   writeValue(root);
4587   writeCommentAfterValueOnSameLine(root);
4588   *document_ << "\n";
4589   document_ = NULL; // Forget the stream, for safety.
4590 }
4591 
writeValue(const Value & value)4592 void StyledStreamWriter::writeValue(const Value& value) {
4593   switch (value.type()) {
4594   case nullValue:
4595     pushValue("null");
4596     break;
4597   case intValue:
4598     pushValue(valueToString(value.asLargestInt()));
4599     break;
4600   case uintValue:
4601     pushValue(valueToString(value.asLargestUInt()));
4602     break;
4603   case realValue:
4604     pushValue(valueToString(value.asDouble()));
4605     break;
4606   case stringValue:
4607   {
4608     // Is NULL possible for value.string_?
4609     char const* str;
4610     char const* end;
4611     bool ok = value.getString(&str, &end);
4612     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4613     else pushValue("");
4614     break;
4615   }
4616   case booleanValue:
4617     pushValue(valueToString(value.asBool()));
4618     break;
4619   case arrayValue:
4620     writeArrayValue(value);
4621     break;
4622   case objectValue: {
4623     Value::Members members(value.getMemberNames());
4624     if (members.empty())
4625       pushValue("{}");
4626     else {
4627       writeWithIndent("{");
4628       indent();
4629       Value::Members::iterator it = members.begin();
4630       for (;;) {
4631         const std::string& name = *it;
4632         const Value& childValue = value[name];
4633         writeCommentBeforeValue(childValue);
4634         writeWithIndent(valueToQuotedString(name.c_str()));
4635         *document_ << " : ";
4636         writeValue(childValue);
4637         if (++it == members.end()) {
4638           writeCommentAfterValueOnSameLine(childValue);
4639           break;
4640         }
4641         *document_ << ",";
4642         writeCommentAfterValueOnSameLine(childValue);
4643       }
4644       unindent();
4645       writeWithIndent("}");
4646     }
4647   } break;
4648   }
4649 }
4650 
writeArrayValue(const Value & value)4651 void StyledStreamWriter::writeArrayValue(const Value& value) {
4652   unsigned size = value.size();
4653   if (size == 0)
4654     pushValue("[]");
4655   else {
4656     bool isArrayMultiLine = isMultineArray(value);
4657     if (isArrayMultiLine) {
4658       writeWithIndent("[");
4659       indent();
4660       bool hasChildValue = !childValues_.empty();
4661       unsigned index = 0;
4662       for (;;) {
4663         const Value& childValue = value[index];
4664         writeCommentBeforeValue(childValue);
4665         if (hasChildValue)
4666           writeWithIndent(childValues_[index]);
4667         else {
4668           if (!indented_) writeIndent();
4669           indented_ = true;
4670           writeValue(childValue);
4671           indented_ = false;
4672         }
4673         if (++index == size) {
4674           writeCommentAfterValueOnSameLine(childValue);
4675           break;
4676         }
4677         *document_ << ",";
4678         writeCommentAfterValueOnSameLine(childValue);
4679       }
4680       unindent();
4681       writeWithIndent("]");
4682     } else // output on a single line
4683     {
4684       assert(childValues_.size() == size);
4685       *document_ << "[ ";
4686       for (unsigned index = 0; index < size; ++index) {
4687         if (index > 0)
4688           *document_ << ", ";
4689         *document_ << childValues_[index];
4690       }
4691       *document_ << " ]";
4692     }
4693   }
4694 }
4695 
isMultineArray(const Value & value)4696 bool StyledStreamWriter::isMultineArray(const Value& value) {
4697   int size = value.size();
4698   bool isMultiLine = size * 3 >= rightMargin_;
4699   childValues_.clear();
4700   for (int index = 0; index < size && !isMultiLine; ++index) {
4701     const Value& childValue = value[index];
4702     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4703                         childValue.size() > 0);
4704   }
4705   if (!isMultiLine) // check if line length > max line length
4706   {
4707     childValues_.reserve(size);
4708     addChildValues_ = true;
4709     int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4710     for (int index = 0; index < size; ++index) {
4711       if (hasCommentForValue(value[index])) {
4712         isMultiLine = true;
4713       }
4714       writeValue(value[index]);
4715       lineLength += int(childValues_[index].length());
4716     }
4717     addChildValues_ = false;
4718     isMultiLine = isMultiLine || lineLength >= rightMargin_;
4719   }
4720   return isMultiLine;
4721 }
4722 
pushValue(const std::string & value)4723 void StyledStreamWriter::pushValue(const std::string& value) {
4724   if (addChildValues_)
4725     childValues_.push_back(value);
4726   else
4727     *document_ << value;
4728 }
4729 
writeIndent()4730 void StyledStreamWriter::writeIndent() {
4731   // blep intended this to look at the so-far-written string
4732   // to determine whether we are already indented, but
4733   // with a stream we cannot do that. So we rely on some saved state.
4734   // The caller checks indented_.
4735   *document_ << '\n' << indentString_;
4736 }
4737 
writeWithIndent(const std::string & value)4738 void StyledStreamWriter::writeWithIndent(const std::string& value) {
4739   if (!indented_) writeIndent();
4740   *document_ << value;
4741   indented_ = false;
4742 }
4743 
indent()4744 void StyledStreamWriter::indent() { indentString_ += indentation_; }
4745 
unindent()4746 void StyledStreamWriter::unindent() {
4747   assert(indentString_.size() >= indentation_.size());
4748   indentString_.resize(indentString_.size() - indentation_.size());
4749 }
4750 
writeCommentBeforeValue(const Value & root)4751 void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
4752   if (!root.hasComment(commentBefore))
4753     return;
4754 
4755   if (!indented_) writeIndent();
4756   const std::string& comment = root.getComment(commentBefore);
4757   std::string::const_iterator iter = comment.begin();
4758   while (iter != comment.end()) {
4759     *document_ << *iter;
4760     if (*iter == '\n' &&
4761        (iter != comment.end() && *(iter + 1) == '/'))
4762       // writeIndent();  // would include newline
4763       *document_ << indentString_;
4764     ++iter;
4765   }
4766   indented_ = false;
4767 }
4768 
writeCommentAfterValueOnSameLine(const Value & root)4769 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
4770   if (root.hasComment(commentAfterOnSameLine))
4771     *document_ << ' ' << root.getComment(commentAfterOnSameLine);
4772 
4773   if (root.hasComment(commentAfter)) {
4774     writeIndent();
4775     *document_ << root.getComment(commentAfter);
4776   }
4777   indented_ = false;
4778 }
4779 
hasCommentForValue(const Value & value)4780 bool StyledStreamWriter::hasCommentForValue(const Value& value) {
4781   return value.hasComment(commentBefore) ||
4782          value.hasComment(commentAfterOnSameLine) ||
4783          value.hasComment(commentAfter);
4784 }
4785 
4786 //////////////////////////
4787 // BuiltStyledStreamWriter
4788 
4789 /// Scoped enums are not available until C++11.
4790 struct CommentStyle {
4791   /// Decide whether to write comments.
4792   enum Enum {
4793     None,  ///< Drop all comments.
4794     Most,  ///< Recover odd behavior of previous versions (not implemented yet).
4795     All  ///< Keep all comments.
4796   };
4797 };
4798 
4799 struct BuiltStyledStreamWriter : public StreamWriter
4800 {
4801   BuiltStyledStreamWriter(
4802       std::string const& indentation,
4803       CommentStyle::Enum cs,
4804       std::string const& colonSymbol,
4805       std::string const& nullSymbol,
4806       std::string const& endingLineFeedSymbol,
4807       bool useSpecialFloats,
4808       unsigned int precision);
4809   int write(Value const& root, std::ostream* sout) override;
4810 private:
4811   void writeValue(Value const& value);
4812   void writeArrayValue(Value const& value);
4813   bool isMultineArray(Value const& value);
4814   void pushValue(std::string const& value);
4815   void writeIndent();
4816   void writeWithIndent(std::string const& value);
4817   void indent();
4818   void unindent();
4819   void writeCommentBeforeValue(Value const& root);
4820   void writeCommentAfterValueOnSameLine(Value const& root);
4821   static bool hasCommentForValue(const Value& value);
4822 
4823   typedef std::vector<std::string> ChildValues;
4824 
4825   ChildValues childValues_;
4826   std::string indentString_;
4827   int rightMargin_;
4828   std::string indentation_;
4829   CommentStyle::Enum cs_;
4830   std::string colonSymbol_;
4831   std::string nullSymbol_;
4832   std::string endingLineFeedSymbol_;
4833   bool addChildValues_ : 1;
4834   bool indented_ : 1;
4835   bool useSpecialFloats_ : 1;
4836   unsigned int precision_;
4837 };
BuiltStyledStreamWriter(std::string const & indentation,CommentStyle::Enum cs,std::string const & colonSymbol,std::string const & nullSymbol,std::string const & endingLineFeedSymbol,bool useSpecialFloats,unsigned int precision)4838 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
4839       std::string const& indentation,
4840       CommentStyle::Enum cs,
4841       std::string const& colonSymbol,
4842       std::string const& nullSymbol,
4843       std::string const& endingLineFeedSymbol,
4844       bool useSpecialFloats,
4845       unsigned int precision)
4846   : rightMargin_(74)
4847   , indentation_(indentation)
4848   , cs_(cs)
4849   , colonSymbol_(colonSymbol)
4850   , nullSymbol_(nullSymbol)
4851   , endingLineFeedSymbol_(endingLineFeedSymbol)
4852   , addChildValues_(false)
4853   , indented_(false)
4854   , useSpecialFloats_(useSpecialFloats)
4855   , precision_(precision)
4856 {
4857 }
write(Value const & root,std::ostream * sout)4858 int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
4859 {
4860   sout_ = sout;
4861   addChildValues_ = false;
4862   indented_ = true;
4863   indentString_ = "";
4864   writeCommentBeforeValue(root);
4865   if (!indented_) writeIndent();
4866   indented_ = true;
4867   writeValue(root);
4868   writeCommentAfterValueOnSameLine(root);
4869   *sout_ << endingLineFeedSymbol_;
4870   sout_ = NULL;
4871   return 0;
4872 }
writeValue(Value const & value)4873 void BuiltStyledStreamWriter::writeValue(Value const& value) {
4874   switch (value.type()) {
4875   case nullValue:
4876     pushValue(nullSymbol_);
4877     break;
4878   case intValue:
4879     pushValue(valueToString(value.asLargestInt()));
4880     break;
4881   case uintValue:
4882     pushValue(valueToString(value.asLargestUInt()));
4883     break;
4884   case realValue:
4885     pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
4886     break;
4887   case stringValue:
4888   {
4889     // Is NULL is possible for value.string_?
4890     char const* str;
4891     char const* end;
4892     bool ok = value.getString(&str, &end);
4893     if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
4894     else pushValue("");
4895     break;
4896   }
4897   case booleanValue:
4898     pushValue(valueToString(value.asBool()));
4899     break;
4900   case arrayValue:
4901     writeArrayValue(value);
4902     break;
4903   case objectValue: {
4904     Value::Members members(value.getMemberNames());
4905     if (members.empty())
4906       pushValue("{}");
4907     else {
4908       writeWithIndent("{");
4909       indent();
4910       Value::Members::iterator it = members.begin();
4911       for (;;) {
4912         std::string const& name = *it;
4913         Value const& childValue = value[name];
4914         writeCommentBeforeValue(childValue);
4915         writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
4916         *sout_ << colonSymbol_;
4917         writeValue(childValue);
4918         if (++it == members.end()) {
4919           writeCommentAfterValueOnSameLine(childValue);
4920           break;
4921         }
4922         *sout_ << ",";
4923         writeCommentAfterValueOnSameLine(childValue);
4924       }
4925       unindent();
4926       writeWithIndent("}");
4927     }
4928   } break;
4929   }
4930 }
4931 
writeArrayValue(Value const & value)4932 void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
4933   unsigned size = value.size();
4934   if (size == 0)
4935     pushValue("[]");
4936   else {
4937     bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
4938     if (isMultiLine) {
4939       writeWithIndent("[");
4940       indent();
4941       bool hasChildValue = !childValues_.empty();
4942       unsigned index = 0;
4943       for (;;) {
4944         Value const& childValue = value[index];
4945         writeCommentBeforeValue(childValue);
4946         if (hasChildValue)
4947           writeWithIndent(childValues_[index]);
4948         else {
4949           if (!indented_) writeIndent();
4950           indented_ = true;
4951           writeValue(childValue);
4952           indented_ = false;
4953         }
4954         if (++index == size) {
4955           writeCommentAfterValueOnSameLine(childValue);
4956           break;
4957         }
4958         *sout_ << ",";
4959         writeCommentAfterValueOnSameLine(childValue);
4960       }
4961       unindent();
4962       writeWithIndent("]");
4963     } else // output on a single line
4964     {
4965       assert(childValues_.size() == size);
4966       *sout_ << "[";
4967       if (!indentation_.empty()) *sout_ << " ";
4968       for (unsigned index = 0; index < size; ++index) {
4969         if (index > 0)
4970           *sout_ << ", ";
4971         *sout_ << childValues_[index];
4972       }
4973       if (!indentation_.empty()) *sout_ << " ";
4974       *sout_ << "]";
4975     }
4976   }
4977 }
4978 
isMultineArray(Value const & value)4979 bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
4980   int size = value.size();
4981   bool isMultiLine = size * 3 >= rightMargin_;
4982   childValues_.clear();
4983   for (int index = 0; index < size && !isMultiLine; ++index) {
4984     Value const& childValue = value[index];
4985     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4986                         childValue.size() > 0);
4987   }
4988   if (!isMultiLine) // check if line length > max line length
4989   {
4990     childValues_.reserve(size);
4991     addChildValues_ = true;
4992     int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4993     for (int index = 0; index < size; ++index) {
4994       if (hasCommentForValue(value[index])) {
4995         isMultiLine = true;
4996       }
4997       writeValue(value[index]);
4998       lineLength += int(childValues_[index].length());
4999     }
5000     addChildValues_ = false;
5001     isMultiLine = isMultiLine || lineLength >= rightMargin_;
5002   }
5003   return isMultiLine;
5004 }
5005 
pushValue(std::string const & value)5006 void BuiltStyledStreamWriter::pushValue(std::string const& value) {
5007   if (addChildValues_)
5008     childValues_.push_back(value);
5009   else
5010     *sout_ << value;
5011 }
5012 
writeIndent()5013 void BuiltStyledStreamWriter::writeIndent() {
5014   // blep intended this to look at the so-far-written string
5015   // to determine whether we are already indented, but
5016   // with a stream we cannot do that. So we rely on some saved state.
5017   // The caller checks indented_.
5018 
5019   if (!indentation_.empty()) {
5020     // In this case, drop newlines too.
5021     *sout_ << '\n' << indentString_;
5022   }
5023 }
5024 
writeWithIndent(std::string const & value)5025 void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
5026   if (!indented_) writeIndent();
5027   *sout_ << value;
5028   indented_ = false;
5029 }
5030 
indent()5031 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
5032 
unindent()5033 void BuiltStyledStreamWriter::unindent() {
5034   assert(indentString_.size() >= indentation_.size());
5035   indentString_.resize(indentString_.size() - indentation_.size());
5036 }
5037 
writeCommentBeforeValue(Value const & root)5038 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
5039   if (cs_ == CommentStyle::None) return;
5040   if (!root.hasComment(commentBefore))
5041     return;
5042 
5043   if (!indented_) writeIndent();
5044   const std::string& comment = root.getComment(commentBefore);
5045   std::string::const_iterator iter = comment.begin();
5046   while (iter != comment.end()) {
5047     *sout_ << *iter;
5048     if (*iter == '\n' &&
5049        (iter != comment.end() && *(iter + 1) == '/'))
5050       // writeIndent();  // would write extra newline
5051       *sout_ << indentString_;
5052     ++iter;
5053   }
5054   indented_ = false;
5055 }
5056 
writeCommentAfterValueOnSameLine(Value const & root)5057 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
5058   if (cs_ == CommentStyle::None) return;
5059   if (root.hasComment(commentAfterOnSameLine))
5060     *sout_ << " " + root.getComment(commentAfterOnSameLine);
5061 
5062   if (root.hasComment(commentAfter)) {
5063     writeIndent();
5064     *sout_ << root.getComment(commentAfter);
5065   }
5066 }
5067 
5068 // static
hasCommentForValue(const Value & value)5069 bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
5070   return value.hasComment(commentBefore) ||
5071          value.hasComment(commentAfterOnSameLine) ||
5072          value.hasComment(commentAfter);
5073 }
5074 
5075 ///////////////
5076 // StreamWriter
5077 
StreamWriter()5078 StreamWriter::StreamWriter()
5079     : sout_(NULL)
5080 {
5081 }
~StreamWriter()5082 StreamWriter::~StreamWriter()
5083 {
5084 }
~Factory()5085 StreamWriter::Factory::~Factory()
5086 {}
StreamWriterBuilder()5087 StreamWriterBuilder::StreamWriterBuilder()
5088 {
5089   setDefaults(&settings_);
5090 }
~StreamWriterBuilder()5091 StreamWriterBuilder::~StreamWriterBuilder()
5092 {}
newStreamWriter() const5093 StreamWriter* StreamWriterBuilder::newStreamWriter() const
5094 {
5095   std::string indentation = settings_["indentation"].asString();
5096   std::string cs_str = settings_["commentStyle"].asString();
5097   bool eyc = settings_["enableYAMLCompatibility"].asBool();
5098   bool dnp = settings_["dropNullPlaceholders"].asBool();
5099   bool usf = settings_["useSpecialFloats"].asBool();
5100   unsigned int pre = settings_["precision"].asUInt();
5101   CommentStyle::Enum cs = CommentStyle::All;
5102   if (cs_str == "All") {
5103     cs = CommentStyle::All;
5104   } else if (cs_str == "None") {
5105     cs = CommentStyle::None;
5106   } else {
5107     throwRuntimeError("commentStyle must be 'All' or 'None'");
5108   }
5109   std::string colonSymbol = " : ";
5110   if (eyc) {
5111     colonSymbol = ": ";
5112   } else if (indentation.empty()) {
5113     colonSymbol = ":";
5114   }
5115   std::string nullSymbol = "null";
5116   if (dnp) {
5117     nullSymbol = "";
5118   }
5119   if (pre > 17) pre = 17;
5120   std::string endingLineFeedSymbol = "";
5121   return new BuiltStyledStreamWriter(
5122       indentation, cs,
5123       colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
5124 }
getValidWriterKeys(std::set<std::string> * valid_keys)5125 static void getValidWriterKeys(std::set<std::string>* valid_keys)
5126 {
5127   valid_keys->clear();
5128   valid_keys->insert("indentation");
5129   valid_keys->insert("commentStyle");
5130   valid_keys->insert("enableYAMLCompatibility");
5131   valid_keys->insert("dropNullPlaceholders");
5132   valid_keys->insert("useSpecialFloats");
5133   valid_keys->insert("precision");
5134 }
validate(Json::Value * invalid) const5135 bool StreamWriterBuilder::validate(Json::Value* invalid) const
5136 {
5137   Json::Value my_invalid;
5138   if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
5139   Json::Value& inv = *invalid;
5140   std::set<std::string> valid_keys;
5141   getValidWriterKeys(&valid_keys);
5142   Value::Members keys = settings_.getMemberNames();
5143   size_t n = keys.size();
5144   for (size_t i = 0; i < n; ++i) {
5145     std::string const& key = keys[i];
5146     if (valid_keys.find(key) == valid_keys.end()) {
5147       inv[key] = settings_[key];
5148     }
5149   }
5150   return 0u == inv.size();
5151 }
operator [](std::string key)5152 Value& StreamWriterBuilder::operator[](std::string key)
5153 {
5154   return settings_[key];
5155 }
5156 // static
setDefaults(Json::Value * settings)5157 void StreamWriterBuilder::setDefaults(Json::Value* settings)
5158 {
5159   //! [StreamWriterBuilderDefaults]
5160   (*settings)["commentStyle"] = "All";
5161   (*settings)["indentation"] = "\t";
5162   (*settings)["enableYAMLCompatibility"] = false;
5163   (*settings)["dropNullPlaceholders"] = false;
5164   (*settings)["useSpecialFloats"] = false;
5165   (*settings)["precision"] = 17;
5166   //! [StreamWriterBuilderDefaults]
5167 }
5168 
writeString(StreamWriter::Factory const & builder,Value const & root)5169 std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
5170   std::ostringstream sout;
5171   StreamWriterPtr const writer(builder.newStreamWriter());
5172   writer->write(root, &sout);
5173   return sout.str();
5174 }
5175 
operator <<(std::ostream & sout,Value const & root)5176 std::ostream& operator<<(std::ostream& sout, Value const& root) {
5177   StreamWriterBuilder builder;
5178   StreamWriterPtr const writer(builder.newStreamWriter());
5179   writer->write(root, &sout);
5180   return sout;
5181 }
5182 
5183 } // namespace Json
5184 
5185 // //////////////////////////////////////////////////////////////////////
5186 // End of content of file: src/lib_json/json_writer.cpp
5187 // //////////////////////////////////////////////////////////////////////
5188 
5189 
5190 
5191 
5192 
5193