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