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