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


mission_planning
Author(s): ivan
autogenerated on Thu Nov 12 2015 19:08:20