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