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