1 /// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
2 /// It is intended to be used with #include "json/json.h"
4 // //////////////////////////////////////////////////////////////////////
5 // Beginning of content of file: LICENSE
6 // //////////////////////////////////////////////////////////////////////
9 The JsonCpp library's source code, including accompanying documentation,
10 tests and demonstration applications, are licensed under the following
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.
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).
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.
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:
29 http://en.wikipedia.org/wiki/MIT_License
31 The full text of the MIT License follows:
33 ========================================================================
34 Copyright (c) 2007-2010 Baptiste Lepilleur
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:
44 The above copyright notice and this permission notice shall be
45 included in all copies or substantial portions of the Software.
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
55 ========================================================================
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
67 // //////////////////////////////////////////////////////////////////////
68 // End of content of file: LICENSE
69 // //////////////////////////////////////////////////////////////////////
71 #include "json/json.h"
73 #ifndef JSON_IS_AMALGAMATION
74 #error "Compile with -I PATH_TO_JSON_DIRECTORY"
77 // //////////////////////////////////////////////////////////////////////
78 // Beginning of content of file: src/lib_json/json_tool.h
79 // //////////////////////////////////////////////////////////////////////
81 // Copyright 2007-2010 Baptiste Lepilleur
82 // Distributed under MIT license, or public domain if desired and
83 // recognized in your jurisdiction.
84 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
86 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
87 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
89 #ifndef NO_LOCALE_SUPPORT
93 /* This header provides common string manipulation support, such as UTF-8,
94 * portable conversion from/to string...
96 * It is an internal header that must not be exposed.
101 static char getDecimalPoint()
103 #ifdef NO_LOCALE_SUPPORT
106 struct lconv *lc = localeconv();
107 return lc ? *(lc->decimal_point) : '\0';
111 /// Converts a unicode code-point to UTF-8.
112 static inline JSONCPP_STRING codePointToUTF8(unsigned int cp)
114 JSONCPP_STRING result;
116 // based on description from http://en.wikipedia.org/wiki/UTF-8
121 result[0] = static_cast<char>(cp);
123 else if (cp <= 0x7FF)
126 result[1] = static_cast<char>(0x80 | (0x3f & cp));
127 result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
129 else if (cp <= 0xFFFF)
132 result[2] = static_cast<char>(0x80 | (0x3f & cp));
133 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
134 result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
136 else if (cp <= 0x10FFFF)
139 result[3] = static_cast<char>(0x80 | (0x3f & cp));
140 result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
141 result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
142 result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
148 /// Returns true if ch is a control character (in range [1,31]).
149 static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
153 /// Constant that specify the size of the buffer that must be passed to
155 uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
158 // Defines a char buffer for use with uintToString().
159 typedef char UIntToStringBuffer[uintToStringBufferSize];
161 /** Converts an unsigned integer to string.
162 * @param value Unsigned interger to convert to string
163 * @param current Input/Output string buffer.
164 * Must have at least uintToStringBufferSize chars free.
166 static inline void uintToString(LargestUInt value, char *¤t)
171 *--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
173 } while (value != 0);
176 /** Change ',' to '.' everywhere in buffer.
178 * We had a sophisticated way, but it did not work in WinCE.
179 * @see https://github.com/open-source-parsers/jsoncpp/pull/9
181 static inline void fixNumericLocale(char *begin, char *end)
193 static inline void fixNumericLocaleInput(char *begin, char *end)
195 char decimalPoint = getDecimalPoint();
196 if (decimalPoint != '\0' && decimalPoint != '.')
202 *begin = decimalPoint;
209 } // namespace Json {
211 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
213 // //////////////////////////////////////////////////////////////////////
214 // End of content of file: src/lib_json/json_tool.h
215 // //////////////////////////////////////////////////////////////////////
217 // //////////////////////////////////////////////////////////////////////
218 // Beginning of content of file: src/lib_json/json_reader.cpp
219 // //////////////////////////////////////////////////////////////////////
221 // Copyright 2007-2011 Baptiste Lepilleur
222 // Distributed under MIT license, or public domain if desired and
223 // recognized in your jurisdiction.
224 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
226 #if !defined(JSON_IS_AMALGAMATION)
227 #include <json/assertions.h>
228 #include <json/reader.h>
229 #include <json/value.h>
230 #include "json_tool.h"
231 #endif // if !defined(JSON_IS_AMALGAMATION)
242 #if defined(_MSC_VER)
243 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
244 #define snprintf sprintf_s
245 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
246 #define snprintf std::snprintf
248 #define snprintf _snprintf
250 #elif defined(__ANDROID__) || defined(__QNXNTO__)
251 #define snprintf snprintf
252 #elif __cplusplus >= 201103L
253 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
254 #define snprintf std::snprintf
258 #if defined(__QNXNTO__)
259 #define sscanf std::sscanf
262 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
263 // Disable warning about strdup being deprecated.
264 #pragma warning(disable : 4996)
267 static int const stackLimit_g = 1000;
268 static int stackDepth_g = 0; // see readValue()
273 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
274 typedef std::unique_ptr<CharReader> CharReaderPtr;
276 typedef std::auto_ptr<CharReader> CharReaderPtr;
279 // Implementation of class Features
280 // ////////////////////////////////
283 : allowComments_(true), strictRoot_(false), allowDroppedNullPlaceholders_(false),
284 allowNumericKeys_(false)
288 Features Features::all() { return Features(); }
290 Features Features::strictMode()
293 features.allowComments_ = false;
294 features.strictRoot_ = true;
295 features.allowDroppedNullPlaceholders_ = false;
296 features.allowNumericKeys_ = false;
300 // Implementation of class Reader
301 // ////////////////////////////////
303 static bool containsNewLine(Reader::Location begin, Reader::Location end)
305 for (; begin < end; ++begin)
306 if (*begin == '\n' || *begin == '\r')
312 // //////////////////////////////////////////////////////////////////
315 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
316 commentsBefore_(), features_(Features::all()), collectComments_()
320 Reader::Reader(const Features &features)
321 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
322 commentsBefore_(), features_(features), collectComments_()
326 bool Reader::parse(const std::string &document, Value &root, bool collectComments)
328 JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
329 std::swap(documentCopy, document_);
330 const char *begin = document_.c_str();
331 const char *end = begin + document_.length();
332 return parse(begin, end, root, collectComments);
335 bool Reader::parse(std::istream &sin, Value &root, bool collectComments)
337 // std::istream_iterator<char> begin(sin);
338 // std::istream_iterator<char> end;
339 // Those would allow streamed input from a file, if parse() were a
340 // template function.
342 // Since JSONCPP_STRING is reference-counted, this at least does not
343 // create an extra copy.
345 std::getline(sin, doc, (char)EOF);
346 return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
349 bool Reader::parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments)
351 if (!features_.allowComments_)
353 collectComments = false;
358 collectComments_ = collectComments;
362 commentsBefore_ = "";
364 while (!nodes_.empty())
368 stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
369 bool successful = readValue();
371 skipCommentTokens(token);
372 if (collectComments_ && !commentsBefore_.empty())
373 root.setComment(commentsBefore_, commentAfter);
374 if (features_.strictRoot_)
376 if (!root.isArray() && !root.isObject())
378 // Set error location to start of doc, ideally should be first token found
380 token.type_ = tokenError;
381 token.start_ = beginDoc;
383 addError("A valid JSON document must be either an array or an object value.", token);
390 bool Reader::readValue()
392 // This is a non-reentrant way to support a stackLimit. Terrible!
393 // But this deprecated class has a security problem: Bad input can
394 // cause a seg-fault. This seems like a fair, binary-compatible way
395 // to prevent the problem.
396 if (stackDepth_g >= stackLimit_g)
397 throwRuntimeError("Exceeded stackLimit in readValue().");
401 skipCommentTokens(token);
402 bool successful = true;
404 if (collectComments_ && !commentsBefore_.empty())
406 currentValue().setComment(commentsBefore_, commentBefore);
407 commentsBefore_ = "";
412 case tokenObjectBegin:
413 successful = readObject(token);
414 currentValue().setOffsetLimit(current_ - begin_);
416 case tokenArrayBegin:
417 successful = readArray(token);
418 currentValue().setOffsetLimit(current_ - begin_);
421 successful = decodeNumber(token);
424 successful = decodeString(token);
429 currentValue().swapPayload(v);
430 currentValue().setOffsetStart(token.start_ - begin_);
431 currentValue().setOffsetLimit(token.end_ - begin_);
437 currentValue().swapPayload(v);
438 currentValue().setOffsetStart(token.start_ - begin_);
439 currentValue().setOffsetLimit(token.end_ - begin_);
445 currentValue().swapPayload(v);
446 currentValue().setOffsetStart(token.start_ - begin_);
447 currentValue().setOffsetLimit(token.end_ - begin_);
450 case tokenArraySeparator:
453 if (features_.allowDroppedNullPlaceholders_)
455 // "Un-read" the current token and mark the current value as a null
459 currentValue().swapPayload(v);
460 currentValue().setOffsetStart(current_ - begin_ - 1);
461 currentValue().setOffsetLimit(current_ - begin_);
463 } // Else, fall through...
465 currentValue().setOffsetStart(token.start_ - begin_);
466 currentValue().setOffsetLimit(token.end_ - begin_);
467 return addError("Syntax error: value, object or array expected.", token);
470 if (collectComments_)
472 lastValueEnd_ = current_;
473 lastValue_ = ¤tValue();
480 void Reader::skipCommentTokens(Token &token)
482 if (features_.allowComments_)
487 } while (token.type_ == tokenComment);
495 bool Reader::readToken(Token &token)
498 token.start_ = current_;
499 Char c = getNextChar();
504 token.type_ = tokenObjectBegin;
507 token.type_ = tokenObjectEnd;
510 token.type_ = tokenArrayBegin;
513 token.type_ = tokenArrayEnd;
516 token.type_ = tokenString;
520 token.type_ = tokenComment;
534 token.type_ = tokenNumber;
538 token.type_ = tokenTrue;
539 ok = match("rue", 3);
542 token.type_ = tokenFalse;
543 ok = match("alse", 4);
546 token.type_ = tokenNull;
547 ok = match("ull", 3);
550 token.type_ = tokenArraySeparator;
553 token.type_ = tokenMemberSeparator;
556 token.type_ = tokenEndOfStream;
563 token.type_ = tokenError;
564 token.end_ = current_;
568 void Reader::skipSpaces()
570 while (current_ != end_)
573 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
580 bool Reader::match(Location pattern, int patternLength)
582 if (end_ - current_ < patternLength)
584 int index = patternLength;
586 if (current_[index] != pattern[index])
588 current_ += patternLength;
592 bool Reader::readComment()
594 Location commentBegin = current_ - 1;
595 Char c = getNextChar();
596 bool successful = false;
598 successful = readCStyleComment();
600 successful = readCppStyleComment();
604 if (collectComments_)
606 CommentPlacement placement = commentBefore;
607 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin))
609 if (c != '*' || !containsNewLine(commentBegin, current_))
610 placement = commentAfterOnSameLine;
613 addComment(commentBegin, current_, placement);
618 static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end)
620 JSONCPP_STRING normalized;
621 normalized.reserve(static_cast<size_t>(end - begin));
622 Reader::Location current = begin;
623 while (current != end)
628 if (current != end && *current == '\n')
642 void Reader::addComment(Location begin, Location end, CommentPlacement placement)
644 assert(collectComments_);
645 const JSONCPP_STRING &normalized = normalizeEOL(begin, end);
646 if (placement == commentAfterOnSameLine)
648 assert(lastValue_ != 0);
649 lastValue_->setComment(normalized, placement);
653 commentsBefore_ += normalized;
657 bool Reader::readCStyleComment()
659 while ((current_ + 1) < end_)
661 Char c = getNextChar();
662 if (c == '*' && *current_ == '/')
665 return getNextChar() == '/';
668 bool Reader::readCppStyleComment()
670 while (current_ != end_)
672 Char c = getNextChar();
677 // Consume DOS EOL. It will be normalized in addComment.
678 if (current_ != end_ && *current_ == '\n')
680 // Break on Moc OS 9 EOL.
687 void Reader::readNumber()
689 const char *p = current_;
690 char c = '0'; // stopgap for already consumed character
692 while (c >= '0' && c <= '9')
693 c = (current_ = p) < end_ ? *p++ : '\0';
697 c = (current_ = p) < end_ ? *p++ : '\0';
698 while (c >= '0' && c <= '9')
699 c = (current_ = p) < end_ ? *p++ : '\0';
702 if (c == 'e' || c == 'E')
704 c = (current_ = p) < end_ ? *p++ : '\0';
705 if (c == '+' || c == '-')
706 c = (current_ = p) < end_ ? *p++ : '\0';
707 while (c >= '0' && c <= '9')
708 c = (current_ = p) < end_ ? *p++ : '\0';
712 bool Reader::readString()
715 while (current_ != end_)
726 bool Reader::readObject(Token &tokenStart)
730 Value init(objectValue);
731 currentValue().swapPayload(init);
732 currentValue().setOffsetStart(tokenStart.start_ - begin_);
733 while (readToken(tokenName))
735 bool initialTokenOk = true;
736 while (tokenName.type_ == tokenComment && initialTokenOk)
737 initialTokenOk = readToken(tokenName);
740 if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
743 if (tokenName.type_ == tokenString)
745 if (!decodeString(tokenName, name))
746 return recoverFromError(tokenObjectEnd);
748 else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_)
751 if (!decodeNumber(tokenName, numberName))
752 return recoverFromError(tokenObjectEnd);
753 name = JSONCPP_STRING(numberName.asCString());
761 if (!readToken(colon) || colon.type_ != tokenMemberSeparator)
763 return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd);
765 Value &value = currentValue()[name];
767 bool ok = readValue();
769 if (!ok) // error already set
770 return recoverFromError(tokenObjectEnd);
773 if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
774 comma.type_ != tokenComment))
776 return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
778 bool finalizeTokenOk = true;
779 while (comma.type_ == tokenComment && finalizeTokenOk)
780 finalizeTokenOk = readToken(comma);
781 if (comma.type_ == tokenObjectEnd)
784 return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd);
787 bool Reader::readArray(Token &tokenStart)
789 Value init(arrayValue);
790 currentValue().swapPayload(init);
791 currentValue().setOffsetStart(tokenStart.start_ - begin_);
793 if (current_ != end_ && *current_ == ']') // empty array
802 Value &value = currentValue()[index++];
804 bool ok = readValue();
806 if (!ok) // error already set
807 return recoverFromError(tokenArrayEnd);
810 // Accept Comment after last item in the array.
811 ok = readToken(token);
812 while (token.type_ == tokenComment && ok)
814 ok = readToken(token);
816 bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
817 if (!ok || badTokenType)
819 return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd);
821 if (token.type_ == tokenArrayEnd)
827 bool Reader::decodeNumber(Token &token)
830 if (!decodeNumber(token, decoded))
832 currentValue().swapPayload(decoded);
833 currentValue().setOffsetStart(token.start_ - begin_);
834 currentValue().setOffsetLimit(token.end_ - begin_);
838 bool Reader::decodeNumber(Token &token, Value &decoded)
840 // Attempts to parse the number as an integer. If the number is
841 // larger than the maximum supported value of an integer then
842 // we decode the number as a double.
843 Location current = token.start_;
844 bool isNegative = *current == '-';
847 // TODO: Help the compiler do the div and mod at compile time or get rid of them.
848 Value::LargestUInt maxIntegerValue =
849 isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1 : Value::maxLargestUInt;
850 Value::LargestUInt threshold = maxIntegerValue / 10;
851 Value::LargestUInt value = 0;
852 while (current < token.end_)
855 if (c < '0' || c > '9')
856 return decodeDouble(token, decoded);
857 Value::UInt digit(static_cast<Value::UInt>(c - '0'));
858 if (value >= threshold)
860 // We've hit or exceeded the max value divided by 10 (rounded down). If
861 // a) we've only just touched the limit, b) this is the last digit, and
862 // c) it's small enough to fit in that rounding delta, we're okay.
863 // Otherwise treat this number as a double to avoid overflow.
864 if (value > threshold || current != token.end_ || digit > maxIntegerValue % 10)
866 return decodeDouble(token, decoded);
869 value = value * 10 + digit;
871 if (isNegative && value == maxIntegerValue)
872 decoded = Value::minLargestInt;
874 decoded = -Value::LargestInt(value);
875 else if (value <= Value::LargestUInt(Value::maxInt))
876 decoded = Value::LargestInt(value);
882 bool Reader::decodeDouble(Token &token)
885 if (!decodeDouble(token, decoded))
887 currentValue().swapPayload(decoded);
888 currentValue().setOffsetStart(token.start_ - begin_);
889 currentValue().setOffsetLimit(token.end_ - begin_);
893 bool Reader::decodeDouble(Token &token, Value &decoded)
896 JSONCPP_STRING buffer(token.start_, token.end_);
897 JSONCPP_ISTRINGSTREAM is(buffer);
899 return addError("'" + JSONCPP_STRING(token.start_, token.end_) + "' is not a number.", token);
904 bool Reader::decodeString(Token &token)
906 JSONCPP_STRING decoded_string;
907 if (!decodeString(token, decoded_string))
909 Value decoded(decoded_string);
910 currentValue().swapPayload(decoded);
911 currentValue().setOffsetStart(token.start_ - begin_);
912 currentValue().setOffsetLimit(token.end_ - begin_);
916 bool Reader::decodeString(Token &token, JSONCPP_STRING &decoded)
918 decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
919 Location current = token.start_ + 1; // skip '"'
920 Location end = token.end_ - 1; // do not include '"'
921 while (current != end)
929 return addError("Empty escape sequence in string", token, current);
930 Char escape = *current++;
959 unsigned int unicode;
960 if (!decodeUnicodeCodePoint(token, current, end, unicode))
962 decoded += codePointToUTF8(unicode);
966 return addError("Bad escape sequence in string", token, current);
977 bool Reader::decodeUnicodeCodePoint(Token &token, Location ¤t, Location end,
978 unsigned int &unicode)
981 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
983 if (unicode >= 0xD800 && unicode <= 0xDBFF)
986 if (end - current < 6)
987 return addError("additional six characters expected to parse unicode surrogate pair.", token,
989 unsigned int surrogatePair;
990 if (*(current++) == '\\' && *(current++) == 'u')
992 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair))
994 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1000 return addError("expecting another \\u token to begin the second half of "
1001 "a unicode surrogate pair",
1007 bool Reader::decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end,
1008 unsigned int &ret_unicode)
1010 if (end - current < 4)
1011 return addError("Bad unicode escape sequence in string: four digits expected.", token, current);
1013 for (int index = 0; index < 4; ++index)
1015 Char c = *current++;
1017 if (c >= '0' && c <= '9')
1019 else if (c >= 'a' && c <= 'f')
1020 unicode += c - 'a' + 10;
1021 else if (c >= 'A' && c <= 'F')
1022 unicode += c - 'A' + 10;
1024 return addError("Bad unicode escape sequence in string: hexadecimal digit expected.", token,
1027 ret_unicode = static_cast<unsigned int>(unicode);
1031 bool Reader::addError(const JSONCPP_STRING &message, Token &token, Location extra)
1034 info.token_ = token;
1035 info.message_ = message;
1036 info.extra_ = extra;
1037 errors_.push_back(info);
1041 bool Reader::recoverFromError(TokenType skipUntilToken)
1043 size_t const errorCount = errors_.size();
1047 if (!readToken(skip))
1048 errors_.resize(errorCount); // discard errors caused by recovery
1049 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
1052 errors_.resize(errorCount);
1056 bool Reader::addErrorAndRecover(const JSONCPP_STRING &message, Token &token,
1057 TokenType skipUntilToken)
1059 addError(message, token);
1060 return recoverFromError(skipUntilToken);
1063 Value &Reader::currentValue() { return *(nodes_.top()); }
1065 Reader::Char Reader::getNextChar()
1067 if (current_ == end_)
1072 void Reader::getLocationLineAndColumn(Location location, int &line, int &column) const
1074 Location current = begin_;
1075 Location lastLineStart = current;
1077 while (current < location && current != end_)
1079 Char c = *current++;
1082 if (*current == '\n')
1084 lastLineStart = current;
1089 lastLineStart = current;
1093 // column & line start at 1
1094 column = int(location - lastLineStart) + 1;
1098 JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const
1101 getLocationLineAndColumn(location, line, column);
1102 char buffer[18 + 16 + 16 + 1];
1103 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
1107 // Deprecated. Preserved for backward compatibility
1108 JSONCPP_STRING Reader::getFormatedErrorMessages() const { return getFormattedErrorMessages(); }
1110 JSONCPP_STRING Reader::getFormattedErrorMessages() const
1112 JSONCPP_STRING formattedMessage;
1113 for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
1115 const ErrorInfo &error = *itError;
1116 formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
1117 formattedMessage += " " + error.message_ + "\n";
1119 formattedMessage += "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
1121 return formattedMessage;
1124 std::vector<Reader::StructuredError> Reader::getStructuredErrors() const
1126 std::vector<Reader::StructuredError> allErrors;
1127 for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
1129 const ErrorInfo &error = *itError;
1130 Reader::StructuredError structured;
1131 structured.offset_start = error.token_.start_ - begin_;
1132 structured.offset_limit = error.token_.end_ - begin_;
1133 structured.message = error.message_;
1134 allErrors.push_back(structured);
1139 bool Reader::pushError(const Value &value, const JSONCPP_STRING &message)
1141 ptrdiff_t const length = end_ - begin_;
1142 if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
1145 token.type_ = tokenError;
1146 token.start_ = begin_ + value.getOffsetStart();
1147 token.end_ = end_ + value.getOffsetLimit();
1149 info.token_ = token;
1150 info.message_ = message;
1152 errors_.push_back(info);
1156 bool Reader::pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra)
1158 ptrdiff_t const length = end_ - begin_;
1159 if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
1160 extra.getOffsetLimit() > length)
1163 token.type_ = tokenError;
1164 token.start_ = begin_ + value.getOffsetStart();
1165 token.end_ = begin_ + value.getOffsetLimit();
1167 info.token_ = token;
1168 info.message_ = message;
1169 info.extra_ = begin_ + extra.getOffsetStart();
1170 errors_.push_back(info);
1174 bool Reader::good() const { return !errors_.size(); }
1176 // exact copy of Features
1180 static OurFeatures all();
1181 bool allowComments_;
1183 bool allowDroppedNullPlaceholders_;
1184 bool allowNumericKeys_;
1185 bool allowSingleQuotes_;
1187 bool rejectDupKeys_;
1188 bool allowSpecialFloats_;
1192 // exact copy of Implementation of class Features
1193 // ////////////////////////////////
1195 OurFeatures OurFeatures::all() { return OurFeatures(); }
1197 // Implementation of class Reader
1198 // ////////////////////////////////
1200 // exact copy of Reader, renamed to OurReader
1205 typedef const Char *Location;
1206 struct StructuredError
1208 ptrdiff_t offset_start;
1209 ptrdiff_t offset_limit;
1210 JSONCPP_STRING message;
1213 OurReader(OurFeatures const &features);
1214 bool parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments = true);
1215 JSONCPP_STRING getFormattedErrorMessages() const;
1216 std::vector<StructuredError> getStructuredErrors() const;
1217 bool pushError(const Value &value, const JSONCPP_STRING &message);
1218 bool pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra);
1222 OurReader(OurReader const &); // no impl
1223 void operator=(OurReader const &); // no impl
1227 tokenEndOfStream = 0,
1240 tokenArraySeparator,
1241 tokenMemberSeparator,
1258 JSONCPP_STRING message_;
1262 typedef std::deque<ErrorInfo> Errors;
1264 bool readToken(Token &token);
1266 bool match(Location pattern, int patternLength);
1268 bool readCStyleComment();
1269 bool readCppStyleComment();
1271 bool readStringSingleQuote();
1272 bool readNumber(bool checkInf);
1274 bool readObject(Token &token);
1275 bool readArray(Token &token);
1276 bool decodeNumber(Token &token);
1277 bool decodeNumber(Token &token, Value &decoded);
1278 bool decodeString(Token &token);
1279 bool decodeString(Token &token, JSONCPP_STRING &decoded);
1280 bool decodeDouble(Token &token);
1281 bool decodeDouble(Token &token, Value &decoded);
1282 bool decodeUnicodeCodePoint(Token &token, Location ¤t, Location end, unsigned int &unicode);
1283 bool decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end,
1284 unsigned int &unicode);
1285 bool addError(const JSONCPP_STRING &message, Token &token, Location extra = 0);
1286 bool recoverFromError(TokenType skipUntilToken);
1287 bool addErrorAndRecover(const JSONCPP_STRING &message, Token &token, TokenType skipUntilToken);
1288 void skipUntilSpace();
1289 Value ¤tValue();
1291 void getLocationLineAndColumn(Location location, int &line, int &column) const;
1292 JSONCPP_STRING getLocationLineAndColumn(Location location) const;
1293 void addComment(Location begin, Location end, CommentPlacement placement);
1294 void skipCommentTokens(Token &token);
1296 typedef std::stack<Value *> Nodes;
1299 JSONCPP_STRING document_;
1303 Location lastValueEnd_;
1305 JSONCPP_STRING commentsBefore_;
1308 OurFeatures const features_;
1309 bool collectComments_;
1312 // complete copy of Read impl, for OurReader
1314 OurReader::OurReader(OurFeatures const &features)
1315 : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(), lastValue_(),
1316 commentsBefore_(), stackDepth_(0), features_(features), collectComments_()
1320 bool OurReader::parse(const char *beginDoc, const char *endDoc, Value &root, bool collectComments)
1322 if (!features_.allowComments_)
1324 collectComments = false;
1329 collectComments_ = collectComments;
1333 commentsBefore_ = "";
1335 while (!nodes_.empty())
1340 bool successful = readValue();
1342 skipCommentTokens(token);
1343 if (features_.failIfExtra_)
1345 if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream)
1347 addError("Extra non-whitespace after JSON value.", token);
1351 if (collectComments_ && !commentsBefore_.empty())
1352 root.setComment(commentsBefore_, commentAfter);
1353 if (features_.strictRoot_)
1355 if (!root.isArray() && !root.isObject())
1357 // Set error location to start of doc, ideally should be first token found
1359 token.type_ = tokenError;
1360 token.start_ = beginDoc;
1361 token.end_ = endDoc;
1362 addError("A valid JSON document must be either an array or an object value.", token);
1369 bool OurReader::readValue()
1371 if (stackDepth_ >= features_.stackLimit_)
1372 throwRuntimeError("Exceeded stackLimit in readValue().");
1375 skipCommentTokens(token);
1376 bool successful = true;
1378 if (collectComments_ && !commentsBefore_.empty())
1380 currentValue().setComment(commentsBefore_, commentBefore);
1381 commentsBefore_ = "";
1384 switch (token.type_)
1386 case tokenObjectBegin:
1387 successful = readObject(token);
1388 currentValue().setOffsetLimit(current_ - begin_);
1390 case tokenArrayBegin:
1391 successful = readArray(token);
1392 currentValue().setOffsetLimit(current_ - begin_);
1395 successful = decodeNumber(token);
1398 successful = decodeString(token);
1403 currentValue().swapPayload(v);
1404 currentValue().setOffsetStart(token.start_ - begin_);
1405 currentValue().setOffsetLimit(token.end_ - begin_);
1411 currentValue().swapPayload(v);
1412 currentValue().setOffsetStart(token.start_ - begin_);
1413 currentValue().setOffsetLimit(token.end_ - begin_);
1419 currentValue().swapPayload(v);
1420 currentValue().setOffsetStart(token.start_ - begin_);
1421 currentValue().setOffsetLimit(token.end_ - begin_);
1426 Value v(std::numeric_limits<double>::quiet_NaN());
1427 currentValue().swapPayload(v);
1428 currentValue().setOffsetStart(token.start_ - begin_);
1429 currentValue().setOffsetLimit(token.end_ - begin_);
1434 Value v(std::numeric_limits<double>::infinity());
1435 currentValue().swapPayload(v);
1436 currentValue().setOffsetStart(token.start_ - begin_);
1437 currentValue().setOffsetLimit(token.end_ - begin_);
1442 Value v(-std::numeric_limits<double>::infinity());
1443 currentValue().swapPayload(v);
1444 currentValue().setOffsetStart(token.start_ - begin_);
1445 currentValue().setOffsetLimit(token.end_ - begin_);
1448 case tokenArraySeparator:
1449 case tokenObjectEnd:
1451 if (features_.allowDroppedNullPlaceholders_)
1453 // "Un-read" the current token and mark the current value as a null
1457 currentValue().swapPayload(v);
1458 currentValue().setOffsetStart(current_ - begin_ - 1);
1459 currentValue().setOffsetLimit(current_ - begin_);
1461 } // else, fall through ...
1463 currentValue().setOffsetStart(token.start_ - begin_);
1464 currentValue().setOffsetLimit(token.end_ - begin_);
1465 return addError("Syntax error: value, object or array expected.", token);
1468 if (collectComments_)
1470 lastValueEnd_ = current_;
1471 lastValue_ = ¤tValue();
1478 void OurReader::skipCommentTokens(Token &token)
1480 if (features_.allowComments_)
1485 } while (token.type_ == tokenComment);
1493 bool OurReader::readToken(Token &token)
1496 token.start_ = current_;
1497 Char c = getNextChar();
1502 token.type_ = tokenObjectBegin;
1505 token.type_ = tokenObjectEnd;
1508 token.type_ = tokenArrayBegin;
1511 token.type_ = tokenArrayEnd;
1514 token.type_ = tokenString;
1518 if (features_.allowSingleQuotes_)
1520 token.type_ = tokenString;
1521 ok = readStringSingleQuote();
1525 token.type_ = tokenComment;
1538 token.type_ = tokenNumber;
1542 if (readNumber(true))
1544 token.type_ = tokenNumber;
1548 token.type_ = tokenNegInf;
1549 ok = features_.allowSpecialFloats_ && match("nfinity", 7);
1553 token.type_ = tokenTrue;
1554 ok = match("rue", 3);
1557 token.type_ = tokenFalse;
1558 ok = match("alse", 4);
1561 token.type_ = tokenNull;
1562 ok = match("ull", 3);
1565 if (features_.allowSpecialFloats_)
1567 token.type_ = tokenNaN;
1568 ok = match("aN", 2);
1576 if (features_.allowSpecialFloats_)
1578 token.type_ = tokenPosInf;
1579 ok = match("nfinity", 7);
1587 token.type_ = tokenArraySeparator;
1590 token.type_ = tokenMemberSeparator;
1593 token.type_ = tokenEndOfStream;
1600 token.type_ = tokenError;
1601 token.end_ = current_;
1605 void OurReader::skipSpaces()
1607 while (current_ != end_)
1610 if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
1617 bool OurReader::match(Location pattern, int patternLength)
1619 if (end_ - current_ < patternLength)
1621 int index = patternLength;
1623 if (current_[index] != pattern[index])
1625 current_ += patternLength;
1629 bool OurReader::readComment()
1631 Location commentBegin = current_ - 1;
1632 Char c = getNextChar();
1633 bool successful = false;
1635 successful = readCStyleComment();
1637 successful = readCppStyleComment();
1641 if (collectComments_)
1643 CommentPlacement placement = commentBefore;
1644 if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin))
1646 if (c != '*' || !containsNewLine(commentBegin, current_))
1647 placement = commentAfterOnSameLine;
1650 addComment(commentBegin, current_, placement);
1655 void OurReader::addComment(Location begin, Location end, CommentPlacement placement)
1657 assert(collectComments_);
1658 const JSONCPP_STRING &normalized = normalizeEOL(begin, end);
1659 if (placement == commentAfterOnSameLine)
1661 assert(lastValue_ != 0);
1662 lastValue_->setComment(normalized, placement);
1666 commentsBefore_ += normalized;
1670 bool OurReader::readCStyleComment()
1672 while ((current_ + 1) < end_)
1674 Char c = getNextChar();
1675 if (c == '*' && *current_ == '/')
1678 return getNextChar() == '/';
1681 bool OurReader::readCppStyleComment()
1683 while (current_ != end_)
1685 Char c = getNextChar();
1690 // Consume DOS EOL. It will be normalized in addComment.
1691 if (current_ != end_ && *current_ == '\n')
1693 // Break on Moc OS 9 EOL.
1700 bool OurReader::readNumber(bool checkInf)
1702 const char *p = current_;
1703 if (checkInf && p != end_ && *p == 'I')
1708 char c = '0'; // stopgap for already consumed character
1710 while (c >= '0' && c <= '9')
1711 c = (current_ = p) < end_ ? *p++ : '\0';
1715 c = (current_ = p) < end_ ? *p++ : '\0';
1716 while (c >= '0' && c <= '9')
1717 c = (current_ = p) < end_ ? *p++ : '\0';
1720 if (c == 'e' || c == 'E')
1722 c = (current_ = p) < end_ ? *p++ : '\0';
1723 if (c == '+' || c == '-')
1724 c = (current_ = p) < end_ ? *p++ : '\0';
1725 while (c >= '0' && c <= '9')
1726 c = (current_ = p) < end_ ? *p++ : '\0';
1730 bool OurReader::readString()
1733 while (current_ != end_)
1744 bool OurReader::readStringSingleQuote()
1747 while (current_ != end_)
1758 bool OurReader::readObject(Token &tokenStart)
1761 JSONCPP_STRING name;
1762 Value init(objectValue);
1763 currentValue().swapPayload(init);
1764 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1765 while (readToken(tokenName))
1767 bool initialTokenOk = true;
1768 while (tokenName.type_ == tokenComment && initialTokenOk)
1769 initialTokenOk = readToken(tokenName);
1770 if (!initialTokenOk)
1772 if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
1775 if (tokenName.type_ == tokenString)
1777 if (!decodeString(tokenName, name))
1778 return recoverFromError(tokenObjectEnd);
1780 else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_)
1783 if (!decodeNumber(tokenName, numberName))
1784 return recoverFromError(tokenObjectEnd);
1785 name = numberName.asString();
1793 if (!readToken(colon) || colon.type_ != tokenMemberSeparator)
1795 return addErrorAndRecover("Missing ':' after object member name", colon, tokenObjectEnd);
1797 if (name.length() >= (1U << 30))
1798 throwRuntimeError("keylength >= 2^30");
1799 if (features_.rejectDupKeys_ && currentValue().isMember(name))
1801 JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
1802 return addErrorAndRecover(msg, tokenName, tokenObjectEnd);
1804 Value &value = currentValue()[name];
1805 nodes_.push(&value);
1806 bool ok = readValue();
1808 if (!ok) // error already set
1809 return recoverFromError(tokenObjectEnd);
1812 if (!readToken(comma) || (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
1813 comma.type_ != tokenComment))
1815 return addErrorAndRecover("Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
1817 bool finalizeTokenOk = true;
1818 while (comma.type_ == tokenComment && finalizeTokenOk)
1819 finalizeTokenOk = readToken(comma);
1820 if (comma.type_ == tokenObjectEnd)
1823 return addErrorAndRecover("Missing '}' or object member name", tokenName, tokenObjectEnd);
1826 bool OurReader::readArray(Token &tokenStart)
1828 Value init(arrayValue);
1829 currentValue().swapPayload(init);
1830 currentValue().setOffsetStart(tokenStart.start_ - begin_);
1832 if (current_ != end_ && *current_ == ']') // empty array
1835 readToken(endArray);
1841 Value &value = currentValue()[index++];
1842 nodes_.push(&value);
1843 bool ok = readValue();
1845 if (!ok) // error already set
1846 return recoverFromError(tokenArrayEnd);
1849 // Accept Comment after last item in the array.
1850 ok = readToken(token);
1851 while (token.type_ == tokenComment && ok)
1853 ok = readToken(token);
1855 bool badTokenType = (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
1856 if (!ok || badTokenType)
1858 return addErrorAndRecover("Missing ',' or ']' in array declaration", token, tokenArrayEnd);
1860 if (token.type_ == tokenArrayEnd)
1866 bool OurReader::decodeNumber(Token &token)
1869 if (!decodeNumber(token, decoded))
1871 currentValue().swapPayload(decoded);
1872 currentValue().setOffsetStart(token.start_ - begin_);
1873 currentValue().setOffsetLimit(token.end_ - begin_);
1877 bool OurReader::decodeNumber(Token &token, Value &decoded)
1879 // Attempts to parse the number as an integer. If the number is
1880 // larger than the maximum supported value of an integer then
1881 // we decode the number as a double.
1882 Location current = token.start_;
1883 bool isNegative = *current == '-';
1886 // TODO: Help the compiler do the div and mod at compile time or get rid of them.
1887 Value::LargestUInt maxIntegerValue =
1888 isNegative ? Value::LargestUInt(-Value::minLargestInt) : Value::maxLargestUInt;
1889 Value::LargestUInt threshold = maxIntegerValue / 10;
1890 Value::LargestUInt value = 0;
1891 while (current < token.end_)
1893 Char c = *current++;
1894 if (c < '0' || c > '9')
1895 return decodeDouble(token, decoded);
1896 Value::UInt digit(static_cast<Value::UInt>(c - '0'));
1897 if (value >= threshold)
1899 // We've hit or exceeded the max value divided by 10 (rounded down). If
1900 // a) we've only just touched the limit, b) this is the last digit, and
1901 // c) it's small enough to fit in that rounding delta, we're okay.
1902 // Otherwise treat this number as a double to avoid overflow.
1903 if (value > threshold || current != token.end_ || digit > maxIntegerValue % 10)
1905 return decodeDouble(token, decoded);
1908 value = value * 10 + digit;
1911 decoded = -Value::LargestInt(value);
1912 else if (value <= Value::LargestUInt(Value::maxInt))
1913 decoded = Value::LargestInt(value);
1919 bool OurReader::decodeDouble(Token &token)
1922 if (!decodeDouble(token, decoded))
1924 currentValue().swapPayload(decoded);
1925 currentValue().setOffsetStart(token.start_ - begin_);
1926 currentValue().setOffsetLimit(token.end_ - begin_);
1930 bool OurReader::decodeDouble(Token &token, Value &decoded)
1933 const int bufferSize = 32;
1935 ptrdiff_t const length = token.end_ - token.start_;
1937 // Sanity check to avoid buffer overflow exploits.
1940 return addError("Unable to parse token length", token);
1942 size_t const ulength = static_cast<size_t>(length);
1944 // Avoid using a string constant for the format control string given to
1945 // sscanf, as this can cause hard to debug crashes on OS X. See here for more
1948 // http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
1949 char format[] = "%lf";
1951 if (length <= bufferSize)
1953 Char buffer[bufferSize + 1];
1954 memcpy(buffer, token.start_, ulength);
1956 fixNumericLocaleInput(buffer, buffer + length);
1957 count = sscanf(buffer, format, &value);
1961 JSONCPP_STRING buffer(token.start_, token.end_);
1962 count = sscanf(buffer.c_str(), format, &value);
1966 return addError("'" + JSONCPP_STRING(token.start_, token.end_) + "' is not a number.", token);
1971 bool OurReader::decodeString(Token &token)
1973 JSONCPP_STRING decoded_string;
1974 if (!decodeString(token, decoded_string))
1976 Value decoded(decoded_string);
1977 currentValue().swapPayload(decoded);
1978 currentValue().setOffsetStart(token.start_ - begin_);
1979 currentValue().setOffsetLimit(token.end_ - begin_);
1983 bool OurReader::decodeString(Token &token, JSONCPP_STRING &decoded)
1985 decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
1986 Location current = token.start_ + 1; // skip '"'
1987 Location end = token.end_ - 1; // do not include '"'
1988 while (current != end)
1990 Char c = *current++;
1996 return addError("Empty escape sequence in string", token, current);
1997 Char escape = *current++;
2026 unsigned int unicode;
2027 if (!decodeUnicodeCodePoint(token, current, end, unicode))
2029 decoded += codePointToUTF8(unicode);
2033 return addError("Bad escape sequence in string", token, current);
2044 bool OurReader::decodeUnicodeCodePoint(Token &token, Location ¤t, Location end,
2045 unsigned int &unicode)
2048 if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
2050 if (unicode >= 0xD800 && unicode <= 0xDBFF)
2053 if (end - current < 6)
2054 return addError("additional six characters expected to parse unicode surrogate pair.", token,
2056 unsigned int surrogatePair;
2057 if (*(current++) == '\\' && *(current++) == 'u')
2059 if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair))
2061 unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
2067 return addError("expecting another \\u token to begin the second half of "
2068 "a unicode surrogate pair",
2074 bool OurReader::decodeUnicodeEscapeSequence(Token &token, Location ¤t, Location end,
2075 unsigned int &ret_unicode)
2077 if (end - current < 4)
2078 return addError("Bad unicode escape sequence in string: four digits expected.", token, current);
2080 for (int index = 0; index < 4; ++index)
2082 Char c = *current++;
2084 if (c >= '0' && c <= '9')
2086 else if (c >= 'a' && c <= 'f')
2087 unicode += c - 'a' + 10;
2088 else if (c >= 'A' && c <= 'F')
2089 unicode += c - 'A' + 10;
2091 return addError("Bad unicode escape sequence in string: hexadecimal digit expected.", token,
2094 ret_unicode = static_cast<unsigned int>(unicode);
2098 bool OurReader::addError(const JSONCPP_STRING &message, Token &token, Location extra)
2101 info.token_ = token;
2102 info.message_ = message;
2103 info.extra_ = extra;
2104 errors_.push_back(info);
2108 bool OurReader::recoverFromError(TokenType skipUntilToken)
2110 size_t errorCount = errors_.size();
2114 if (!readToken(skip))
2115 errors_.resize(errorCount); // discard errors caused by recovery
2116 if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
2119 errors_.resize(errorCount);
2123 bool OurReader::addErrorAndRecover(const JSONCPP_STRING &message, Token &token,
2124 TokenType skipUntilToken)
2126 addError(message, token);
2127 return recoverFromError(skipUntilToken);
2130 Value &OurReader::currentValue() { return *(nodes_.top()); }
2132 OurReader::Char OurReader::getNextChar()
2134 if (current_ == end_)
2139 void OurReader::getLocationLineAndColumn(Location location, int &line, int &column) const
2141 Location current = begin_;
2142 Location lastLineStart = current;
2144 while (current < location && current != end_)
2146 Char c = *current++;
2149 if (*current == '\n')
2151 lastLineStart = current;
2156 lastLineStart = current;
2160 // column & line start at 1
2161 column = int(location - lastLineStart) + 1;
2165 JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const
2168 getLocationLineAndColumn(location, line, column);
2169 char buffer[18 + 16 + 16 + 1];
2170 snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
2174 JSONCPP_STRING OurReader::getFormattedErrorMessages() const
2176 JSONCPP_STRING formattedMessage;
2177 for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
2179 const ErrorInfo &error = *itError;
2180 formattedMessage += "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
2181 formattedMessage += " " + error.message_ + "\n";
2183 formattedMessage += "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
2185 return formattedMessage;
2188 std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const
2190 std::vector<OurReader::StructuredError> allErrors;
2191 for (Errors::const_iterator itError = errors_.begin(); itError != errors_.end(); ++itError)
2193 const ErrorInfo &error = *itError;
2194 OurReader::StructuredError structured;
2195 structured.offset_start = error.token_.start_ - begin_;
2196 structured.offset_limit = error.token_.end_ - begin_;
2197 structured.message = error.message_;
2198 allErrors.push_back(structured);
2203 bool OurReader::pushError(const Value &value, const JSONCPP_STRING &message)
2205 ptrdiff_t length = end_ - begin_;
2206 if (value.getOffsetStart() > length || value.getOffsetLimit() > length)
2209 token.type_ = tokenError;
2210 token.start_ = begin_ + value.getOffsetStart();
2211 token.end_ = end_ + value.getOffsetLimit();
2213 info.token_ = token;
2214 info.message_ = message;
2216 errors_.push_back(info);
2220 bool OurReader::pushError(const Value &value, const JSONCPP_STRING &message, const Value &extra)
2222 ptrdiff_t length = end_ - begin_;
2223 if (value.getOffsetStart() > length || value.getOffsetLimit() > length ||
2224 extra.getOffsetLimit() > length)
2227 token.type_ = tokenError;
2228 token.start_ = begin_ + value.getOffsetStart();
2229 token.end_ = begin_ + value.getOffsetLimit();
2231 info.token_ = token;
2232 info.message_ = message;
2233 info.extra_ = begin_ + extra.getOffsetStart();
2234 errors_.push_back(info);
2238 bool OurReader::good() const { return !errors_.size(); }
2240 class OurCharReader : public CharReader
2242 bool const collectComments_;
2246 OurCharReader(bool collectComments, OurFeatures const &features)
2247 : collectComments_(collectComments), reader_(features)
2250 bool parse(char const *beginDoc, char const *endDoc, Value *root,
2251 JSONCPP_STRING *errs) JSONCPP_OVERRIDE
2253 bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
2256 *errs = reader_.getFormattedErrorMessages();
2262 CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
2263 CharReaderBuilder::~CharReaderBuilder() {}
2264 CharReader *CharReaderBuilder::newCharReader() const
2266 bool collectComments = settings_["collectComments"].asBool();
2267 OurFeatures features = OurFeatures::all();
2268 features.allowComments_ = settings_["allowComments"].asBool();
2269 features.strictRoot_ = settings_["strictRoot"].asBool();
2270 features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
2271 features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
2272 features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
2273 features.stackLimit_ = settings_["stackLimit"].asInt();
2274 features.failIfExtra_ = settings_["failIfExtra"].asBool();
2275 features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
2276 features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
2277 return new OurCharReader(collectComments, features);
2279 static void getValidReaderKeys(std::set<JSONCPP_STRING> *valid_keys)
2281 valid_keys->clear();
2282 valid_keys->insert("collectComments");
2283 valid_keys->insert("allowComments");
2284 valid_keys->insert("strictRoot");
2285 valid_keys->insert("allowDroppedNullPlaceholders");
2286 valid_keys->insert("allowNumericKeys");
2287 valid_keys->insert("allowSingleQuotes");
2288 valid_keys->insert("stackLimit");
2289 valid_keys->insert("failIfExtra");
2290 valid_keys->insert("rejectDupKeys");
2291 valid_keys->insert("allowSpecialFloats");
2293 bool CharReaderBuilder::validate(Json::Value *invalid) const
2295 Json::Value my_invalid;
2297 invalid = &my_invalid; // so we do not need to test for NULL
2298 Json::Value &inv = *invalid;
2299 std::set<JSONCPP_STRING> valid_keys;
2300 getValidReaderKeys(&valid_keys);
2301 Value::Members keys = settings_.getMemberNames();
2302 size_t n = keys.size();
2303 for (size_t i = 0; i < n; ++i)
2305 JSONCPP_STRING const &key = keys[i];
2306 if (valid_keys.find(key) == valid_keys.end())
2308 inv[key] = settings_[key];
2311 return 0u == inv.size();
2313 Value &CharReaderBuilder::operator[](JSONCPP_STRING key) { return settings_[key]; }
2315 void CharReaderBuilder::strictMode(Json::Value *settings)
2317 //! [CharReaderBuilderStrictMode]
2318 (*settings)["allowComments"] = false;
2319 (*settings)["strictRoot"] = true;
2320 (*settings)["allowDroppedNullPlaceholders"] = false;
2321 (*settings)["allowNumericKeys"] = false;
2322 (*settings)["allowSingleQuotes"] = false;
2323 (*settings)["stackLimit"] = 1000;
2324 (*settings)["failIfExtra"] = true;
2325 (*settings)["rejectDupKeys"] = true;
2326 (*settings)["allowSpecialFloats"] = false;
2327 //! [CharReaderBuilderStrictMode]
2330 void CharReaderBuilder::setDefaults(Json::Value *settings)
2332 //! [CharReaderBuilderDefaults]
2333 (*settings)["collectComments"] = true;
2334 (*settings)["allowComments"] = true;
2335 (*settings)["strictRoot"] = false;
2336 (*settings)["allowDroppedNullPlaceholders"] = false;
2337 (*settings)["allowNumericKeys"] = false;
2338 (*settings)["allowSingleQuotes"] = false;
2339 (*settings)["stackLimit"] = 1000;
2340 (*settings)["failIfExtra"] = false;
2341 (*settings)["rejectDupKeys"] = false;
2342 (*settings)["allowSpecialFloats"] = false;
2343 //! [CharReaderBuilderDefaults]
2346 //////////////////////////////////
2349 bool parseFromStream(CharReader::Factory const &fact, JSONCPP_ISTREAM &sin, Value *root,
2350 JSONCPP_STRING *errs)
2352 JSONCPP_OSTRINGSTREAM ssin;
2353 ssin << sin.rdbuf();
2354 JSONCPP_STRING doc = ssin.str();
2355 char const *begin = doc.data();
2356 char const *end = begin + doc.size();
2357 // Note that we do not actually need a null-terminator.
2358 CharReaderPtr const reader(fact.newCharReader());
2359 return reader->parse(begin, end, root, errs);
2362 JSONCPP_ISTREAM &operator>>(JSONCPP_ISTREAM &sin, Value &root)
2364 CharReaderBuilder b;
2365 JSONCPP_STRING errs;
2366 bool ok = parseFromStream(b, sin, &root, &errs);
2369 fprintf(stderr, "Error from reader: %s", errs.c_str());
2371 throwRuntimeError(errs);
2378 // //////////////////////////////////////////////////////////////////////
2379 // End of content of file: src/lib_json/json_reader.cpp
2380 // //////////////////////////////////////////////////////////////////////
2382 // //////////////////////////////////////////////////////////////////////
2383 // Beginning of content of file: src/lib_json/json_valueiterator.inl
2384 // //////////////////////////////////////////////////////////////////////
2386 // Copyright 2007-2010 Baptiste Lepilleur
2387 // Distributed under MIT license, or public domain if desired and
2388 // recognized in your jurisdiction.
2389 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2391 // included by json_value.cpp
2396 // //////////////////////////////////////////////////////////////////
2397 // //////////////////////////////////////////////////////////////////
2398 // //////////////////////////////////////////////////////////////////
2399 // class ValueIteratorBase
2400 // //////////////////////////////////////////////////////////////////
2401 // //////////////////////////////////////////////////////////////////
2402 // //////////////////////////////////////////////////////////////////
2404 ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
2406 ValueIteratorBase::ValueIteratorBase(const Value::ObjectValues::iterator ¤t)
2407 : current_(current), isNull_(false)
2411 Value &ValueIteratorBase::deref() const { return current_->second; }
2413 void ValueIteratorBase::increment() { ++current_; }
2415 void ValueIteratorBase::decrement() { --current_; }
2417 ValueIteratorBase::difference_type ValueIteratorBase::computeDistance(const SelfType &other) const
2419 #ifdef JSON_USE_CPPTL_SMALLMAP
2420 return other.current_ - current_;
2422 // Iterator for null value are initialized using the default
2423 // constructor, which initialize current_ to the default
2424 // std::map::iterator. As begin() and end() are two instance
2425 // of the default std::map::iterator, they can not be compared.
2426 // To allow this, we handle this comparison specifically.
2427 if (isNull_ && other.isNull_)
2432 // Usage of std::distance is not portable (does not compile with Sun Studio 12
2434 // which is the one used by default).
2435 // Using a portable hand-made version for non random iterator instead:
2436 // return difference_type( std::distance( current_, other.current_ ) );
2437 difference_type myDistance = 0;
2438 for (Value::ObjectValues::iterator it = current_; it != other.current_; ++it)
2446 bool ValueIteratorBase::isEqual(const SelfType &other) const
2450 return other.isNull_;
2452 return current_ == other.current_;
2455 void ValueIteratorBase::copy(const SelfType &other)
2457 current_ = other.current_;
2458 isNull_ = other.isNull_;
2461 Value ValueIteratorBase::key() const
2463 const Value::CZString czstring = (*current_).first;
2464 if (czstring.data())
2466 if (czstring.isStaticString())
2467 return Value(StaticString(czstring.data()));
2468 return Value(czstring.data(), czstring.data() + czstring.length());
2470 return Value(czstring.index());
2473 UInt ValueIteratorBase::index() const
2475 const Value::CZString czstring = (*current_).first;
2476 if (!czstring.data())
2477 return czstring.index();
2478 return Value::UInt(-1);
2481 JSONCPP_STRING ValueIteratorBase::name() const
2485 keey = memberName(&end);
2487 return JSONCPP_STRING();
2488 return JSONCPP_STRING(keey, end);
2491 char const *ValueIteratorBase::memberName() const
2493 const char *cname = (*current_).first.data();
2494 return cname ? cname : "";
2497 char const *ValueIteratorBase::memberName(char const **end) const
2499 const char *cname = (*current_).first.data();
2505 *end = cname + (*current_).first.length();
2509 // //////////////////////////////////////////////////////////////////
2510 // //////////////////////////////////////////////////////////////////
2511 // //////////////////////////////////////////////////////////////////
2512 // class ValueConstIterator
2513 // //////////////////////////////////////////////////////////////////
2514 // //////////////////////////////////////////////////////////////////
2515 // //////////////////////////////////////////////////////////////////
2517 ValueConstIterator::ValueConstIterator() {}
2519 ValueConstIterator::ValueConstIterator(const Value::ObjectValues::iterator ¤t)
2520 : ValueIteratorBase(current)
2524 ValueConstIterator::ValueConstIterator(ValueIterator const &other) : ValueIteratorBase(other) {}
2526 ValueConstIterator &ValueConstIterator::operator=(const ValueIteratorBase &other)
2532 // //////////////////////////////////////////////////////////////////
2533 // //////////////////////////////////////////////////////////////////
2534 // //////////////////////////////////////////////////////////////////
2535 // class ValueIterator
2536 // //////////////////////////////////////////////////////////////////
2537 // //////////////////////////////////////////////////////////////////
2538 // //////////////////////////////////////////////////////////////////
2540 ValueIterator::ValueIterator() {}
2542 ValueIterator::ValueIterator(const Value::ObjectValues::iterator ¤t)
2543 : ValueIteratorBase(current)
2547 ValueIterator::ValueIterator(const ValueConstIterator &other) : ValueIteratorBase(other)
2549 throwRuntimeError("ConstIterator to Iterator should never be allowed.");
2552 ValueIterator::ValueIterator(const ValueIterator &other) : ValueIteratorBase(other) {}
2554 ValueIterator &ValueIterator::operator=(const SelfType &other)
2562 // //////////////////////////////////////////////////////////////////////
2563 // End of content of file: src/lib_json/json_valueiterator.inl
2564 // //////////////////////////////////////////////////////////////////////
2566 // //////////////////////////////////////////////////////////////////////
2567 // Beginning of content of file: src/lib_json/json_value.cpp
2568 // //////////////////////////////////////////////////////////////////////
2570 // Copyright 2011 Baptiste Lepilleur
2571 // Distributed under MIT license, or public domain if desired and
2572 // recognized in your jurisdiction.
2573 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
2575 #if !defined(JSON_IS_AMALGAMATION)
2576 #include <json/assertions.h>
2577 #include <json/value.h>
2578 #include <json/writer.h>
2579 #endif // if !defined(JSON_IS_AMALGAMATION)
2585 #ifdef JSON_USE_CPPTL
2586 #include <cpptl/conststring.h>
2588 #include <cstddef> // size_t
2589 #include <algorithm> // min()
2591 #define JSON_ASSERT_UNREACHABLE assert(false)
2596 // This is a walkaround to avoid the static initialization of Value::null.
2597 // kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
2598 // 8 (instead of 4) as a bit of future-proofing.
2599 #if defined(__ARMEL__)
2600 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
2602 #define ALIGNAS(byte_alignment)
2604 // static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
2605 // const unsigned char& kNullRef = kNull[0];
2606 // const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
2607 // const Value& Value::nullRef = null;
2610 Value const &Value::nullSingleton()
2612 static Value const nullStatic;
2616 // for backwards compatibility, we'll leave these global references around, but DO NOT
2617 // use them in JSONCPP library code any more!
2618 Value const &Value::null = Value::nullSingleton();
2619 Value const &Value::nullRef = Value::nullSingleton();
2621 const Int Value::minInt = Int(~(UInt(-1) / 2));
2622 const Int Value::maxInt = Int(UInt(-1) / 2);
2623 const UInt Value::maxUInt = UInt(-1);
2624 #if defined(JSON_HAS_INT64)
2625 const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
2626 const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
2627 const UInt64 Value::maxUInt64 = UInt64(-1);
2628 // The constant is hard-coded because some compiler have trouble
2629 // converting Value::maxUInt64 to a double correctly (AIX/xlC).
2630 // Assumes that UInt64 is a 64 bits integer.
2631 static const double maxUInt64AsDouble = 18446744073709551615.0;
2632 #endif // defined(JSON_HAS_INT64)
2633 const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
2634 const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
2635 const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
2637 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2638 template <typename T, typename U> static inline bool InRange(double d, T min, U max)
2640 // The casts can lose precision, but we are looking only for
2641 // an approximate range. Might fail on edge cases though. ~cdunn
2642 // return d >= static_cast<double>(min) && d <= static_cast<double>(max);
2643 return d >= min && d <= max;
2645 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2646 static inline double integerToDouble(Json::UInt64 value)
2648 return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
2651 template <typename T> static inline double integerToDouble(T value)
2653 return static_cast<double>(value);
2656 template <typename T, typename U> static inline bool InRange(double d, T min, U max)
2658 return d >= integerToDouble(min) && d <= integerToDouble(max);
2660 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2662 /** Duplicates the specified string value.
2663 * @param value Pointer to the string to duplicate. Must be zero-terminated if
2664 * length is "unknown".
2665 * @param length Length of the value. if equals to unknown, then it will be
2666 * computed using strlen(value).
2667 * @return Pointer on the duplicate instance of string.
2669 static inline char *duplicateStringValue(const char *value, size_t length)
2671 // Avoid an integer overflow in the call to malloc below by limiting length
2673 if (length >= static_cast<size_t>(Value::maxInt))
2674 length = Value::maxInt - 1;
2676 char *newString = static_cast<char *>(malloc(length + 1));
2677 if (newString == NULL)
2679 throwRuntimeError("in Json::Value::duplicateStringValue(): "
2680 "Failed to allocate string value buffer");
2682 memcpy(newString, value, length);
2683 newString[length] = 0;
2687 /* Record the length as a prefix.
2689 static inline char *duplicateAndPrefixStringValue(const char *value, unsigned int length)
2691 // Avoid an integer overflow in the call to malloc below by limiting length
2693 JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
2694 "in Json::Value::duplicateAndPrefixStringValue(): "
2695 "length too big for prefixing");
2696 unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
2697 char *newString = static_cast<char *>(malloc(actualLength));
2700 throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
2701 "Failed to allocate string value buffer");
2703 *reinterpret_cast<unsigned *>(newString) = length;
2704 memcpy(newString + sizeof(unsigned), value, length);
2705 newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
2708 inline static void decodePrefixedString(bool isPrefixed, char const *prefixed, unsigned *length,
2713 *length = static_cast<unsigned>(strlen(prefixed));
2718 *length = *reinterpret_cast<unsigned const *>(prefixed);
2719 *value = prefixed + sizeof(unsigned);
2722 /** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
2724 #if JSONCPP_USING_SECURE_MEMORY
2725 static inline void releasePrefixedStringValue(char *value)
2727 unsigned length = 0;
2728 char const *valueDecoded;
2729 decodePrefixedString(true, value, &length, &valueDecoded);
2730 size_t const size = sizeof(unsigned) + length + 1U;
2731 memset(value, 0, size);
2734 static inline void releaseStringValue(char *value, unsigned length)
2736 // length==0 => we allocated the strings memory
2737 size_t size = (length == 0) ? strlen(value) : length;
2738 memset(value, 0, size);
2741 #else // !JSONCPP_USING_SECURE_MEMORY
2742 static inline void releasePrefixedStringValue(char *value) { free(value); }
2743 static inline void releaseStringValue(char *value, unsigned) { free(value); }
2744 #endif // JSONCPP_USING_SECURE_MEMORY
2748 // //////////////////////////////////////////////////////////////////
2749 // //////////////////////////////////////////////////////////////////
2750 // //////////////////////////////////////////////////////////////////
2751 // ValueInternals...
2752 // //////////////////////////////////////////////////////////////////
2753 // //////////////////////////////////////////////////////////////////
2754 // //////////////////////////////////////////////////////////////////
2755 #if !defined(JSON_IS_AMALGAMATION)
2757 #include "json_valueiterator.inl"
2758 #endif // if !defined(JSON_IS_AMALGAMATION)
2763 Exception::Exception(JSONCPP_STRING const &msg) : msg_(msg) {}
2764 Exception::~Exception() throw() {}
2765 char const *Exception::what() const throw() { return msg_.c_str(); }
2766 RuntimeError::RuntimeError(JSONCPP_STRING const &msg) : Exception(msg) {}
2767 LogicError::LogicError(JSONCPP_STRING const &msg) : Exception(msg) {}
2768 JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const &msg) { throw RuntimeError(msg); }
2769 JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const &msg) { throw LogicError(msg); }
2771 // //////////////////////////////////////////////////////////////////
2772 // //////////////////////////////////////////////////////////////////
2773 // //////////////////////////////////////////////////////////////////
2774 // class Value::CommentInfo
2775 // //////////////////////////////////////////////////////////////////
2776 // //////////////////////////////////////////////////////////////////
2777 // //////////////////////////////////////////////////////////////////
2779 Value::CommentInfo::CommentInfo() : comment_(0) {}
2781 Value::CommentInfo::~CommentInfo()
2784 releaseStringValue(comment_, 0u);
2787 void Value::CommentInfo::setComment(const char *text, size_t len)
2791 releaseStringValue(comment_, 0u);
2794 JSON_ASSERT(text != 0);
2795 JSON_ASSERT_MESSAGE(text[0] == '\0' || text[0] == '/',
2796 "in Json::Value::setComment(): Comments must start with /");
2797 // It seems that /**/ style comments are acceptable as well.
2798 comment_ = duplicateStringValue(text, len);
2801 // //////////////////////////////////////////////////////////////////
2802 // //////////////////////////////////////////////////////////////////
2803 // //////////////////////////////////////////////////////////////////
2804 // class Value::CZString
2805 // //////////////////////////////////////////////////////////////////
2806 // //////////////////////////////////////////////////////////////////
2807 // //////////////////////////////////////////////////////////////////
2809 // Notes: policy_ indicates if the string was allocated when
2810 // a string is stored.
2812 Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
2814 Value::CZString::CZString(char const *str, unsigned ulength, DuplicationPolicy allocate)
2817 // allocate != duplicate
2818 storage_.policy_ = allocate & 0x3;
2819 storage_.length_ = ulength & 0x3FFFFFFF;
2822 Value::CZString::CZString(const CZString &other)
2824 cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
2825 ? duplicateStringValue(other.cstr_, other.storage_.length_)
2828 static_cast<unsigned>(
2829 other.cstr_ ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
2832 : static_cast<DuplicationPolicy>(other.storage_.policy_)) &
2834 storage_.length_ = other.storage_.length_;
2837 #if JSON_HAS_RVALUE_REFERENCES
2838 Value::CZString::CZString(CZString &&other) : cstr_(other.cstr_), index_(other.index_)
2840 other.cstr_ = nullptr;
2844 Value::CZString::~CZString()
2846 if (cstr_ && storage_.policy_ == duplicate)
2848 releaseStringValue(const_cast<char *>(cstr_), storage_.length_ + 1u); //+1 for null terminating
2849 // character for sake of
2850 // completeness but not
2851 // actually necessary
2855 void Value::CZString::swap(CZString &other)
2857 std::swap(cstr_, other.cstr_);
2858 std::swap(index_, other.index_);
2861 Value::CZString &Value::CZString::operator=(CZString other)
2867 bool Value::CZString::operator<(const CZString &other) const
2870 return index_ < other.index_;
2871 // return strcmp(cstr_, other.cstr_) < 0;
2872 // Assume both are strings.
2873 unsigned this_len = this->storage_.length_;
2874 unsigned other_len = other.storage_.length_;
2875 unsigned min_len = std::min(this_len, other_len);
2876 JSON_ASSERT(this->cstr_ && other.cstr_);
2877 int comp = memcmp(this->cstr_, other.cstr_, min_len);
2882 return (this_len < other_len);
2885 bool Value::CZString::operator==(const CZString &other) const
2888 return index_ == other.index_;
2889 // return strcmp(cstr_, other.cstr_) == 0;
2890 // Assume both are strings.
2891 unsigned this_len = this->storage_.length_;
2892 unsigned other_len = other.storage_.length_;
2893 if (this_len != other_len)
2895 JSON_ASSERT(this->cstr_ && other.cstr_);
2896 int comp = memcmp(this->cstr_, other.cstr_, this_len);
2900 ArrayIndex Value::CZString::index() const { return index_; }
2902 // const char* Value::CZString::c_str() const { return cstr_; }
2903 const char *Value::CZString::data() const { return cstr_; }
2904 unsigned Value::CZString::length() const { return storage_.length_; }
2905 bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
2907 // //////////////////////////////////////////////////////////////////
2908 // //////////////////////////////////////////////////////////////////
2909 // //////////////////////////////////////////////////////////////////
2910 // class Value::Value
2911 // //////////////////////////////////////////////////////////////////
2912 // //////////////////////////////////////////////////////////////////
2913 // //////////////////////////////////////////////////////////////////
2915 /*! \internal Default constructor initialization must be equivalent to:
2916 * memset( this, 0, sizeof(Value) )
2917 * This optimization is used in ValueInternalMap fast allocator.
2919 Value::Value(ValueType vtype)
2921 static char const empty[] = "";
2935 // allocated_ == false, so this is safe.
2936 value_.string_ = const_cast<char *>(static_cast<char const *>(empty));
2940 value_.map_ = new ObjectValues();
2943 value_.bool_ = false;
2946 JSON_ASSERT_UNREACHABLE;
2950 Value::Value(Int value)
2952 initBasic(intValue);
2953 value_.int_ = value;
2956 Value::Value(UInt value)
2958 initBasic(uintValue);
2959 value_.uint_ = value;
2961 #if defined(JSON_HAS_INT64)
2962 Value::Value(Int64 value)
2964 initBasic(intValue);
2965 value_.int_ = value;
2967 Value::Value(UInt64 value)
2969 initBasic(uintValue);
2970 value_.uint_ = value;
2972 #endif // defined(JSON_HAS_INT64)
2974 Value::Value(double value)
2976 initBasic(realValue);
2977 value_.real_ = value;
2980 Value::Value(const char *value)
2982 initBasic(stringValue, true);
2983 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
2986 Value::Value(const char *beginValue, const char *endValue)
2988 initBasic(stringValue, true);
2990 duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
2993 Value::Value(const JSONCPP_STRING &value)
2995 initBasic(stringValue, true);
2997 duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
3000 Value::Value(const StaticString &value)
3002 initBasic(stringValue);
3003 value_.string_ = const_cast<char *>(value.c_str());
3006 #ifdef JSON_USE_CPPTL
3007 Value::Value(const CppTL::ConstString &value)
3009 initBasic(stringValue, true);
3010 value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
3014 Value::Value(bool value)
3016 initBasic(booleanValue);
3017 value_.bool_ = value;
3020 Value::Value(Value const &other)
3021 : type_(other.type_), allocated_(false), comments_(0), start_(other.start_),
3022 limit_(other.limit_)
3031 value_ = other.value_;
3034 if (other.value_.string_ && other.allocated_)
3038 decodePrefixedString(other.allocated_, other.value_.string_, &len, &str);
3039 value_.string_ = duplicateAndPrefixStringValue(str, len);
3044 value_.string_ = other.value_.string_;
3050 value_.map_ = new ObjectValues(*other.value_.map_);
3053 JSON_ASSERT_UNREACHABLE;
3055 if (other.comments_)
3057 comments_ = new CommentInfo[numberOfCommentPlacement];
3058 for (int comment = 0; comment < numberOfCommentPlacement; ++comment)
3060 const CommentInfo &otherComment = other.comments_[comment];
3061 if (otherComment.comment_)
3062 comments_[comment].setComment(otherComment.comment_, strlen(otherComment.comment_));
3067 #if JSON_HAS_RVALUE_REFERENCES
3069 Value::Value(Value &&other)
3071 initBasic(nullValue);
3088 releasePrefixedStringValue(value_.string_);
3095 JSON_ASSERT_UNREACHABLE;
3103 Value &Value::operator=(Value other)
3109 void Value::swapPayload(Value &other)
3111 ValueType temp = type_;
3112 type_ = other.type_;
3114 std::swap(value_, other.value_);
3115 int temp2 = allocated_;
3116 allocated_ = other.allocated_;
3117 other.allocated_ = temp2 & 0x1;
3120 void Value::swap(Value &other)
3123 std::swap(comments_, other.comments_);
3124 std::swap(start_, other.start_);
3125 std::swap(limit_, other.limit_);
3128 ValueType Value::type() const { return type_; }
3130 int Value::compare(const Value &other) const
3139 bool Value::operator<(const Value &other) const
3141 int typeDelta = type_ - other.type_;
3143 return typeDelta < 0 ? true : false;
3149 return value_.int_ < other.value_.int_;
3151 return value_.uint_ < other.value_.uint_;
3153 return value_.real_ < other.value_.real_;
3155 return value_.bool_ < other.value_.bool_;
3158 if ((value_.string_ == 0) || (other.value_.string_ == 0))
3160 if (other.value_.string_)
3167 char const *this_str;
3168 char const *other_str;
3169 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3170 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3171 unsigned min_len = std::min(this_len, other_len);
3172 JSON_ASSERT(this_str && other_str);
3173 int comp = memcmp(this_str, other_str, min_len);
3178 return (this_len < other_len);
3183 int delta = int(value_.map_->size() - other.value_.map_->size());
3186 return (*value_.map_) < (*other.value_.map_);
3189 JSON_ASSERT_UNREACHABLE;
3191 return false; // unreachable
3194 bool Value::operator<=(const Value &other) const { return !(other < *this); }
3196 bool Value::operator>=(const Value &other) const { return !(*this < other); }
3198 bool Value::operator>(const Value &other) const { return other < *this; }
3200 bool Value::operator==(const Value &other) const
3202 // if ( type_ != other.type_ )
3204 // attempt to take address of bit-field structure member `Json::Value::type_'
3205 // Beats me, but a temp solves the problem.
3206 int temp = other.type_;
3214 return value_.int_ == other.value_.int_;
3216 return value_.uint_ == other.value_.uint_;
3218 return value_.real_ == other.value_.real_;
3220 return value_.bool_ == other.value_.bool_;
3223 if ((value_.string_ == 0) || (other.value_.string_ == 0))
3225 return (value_.string_ == other.value_.string_);
3229 char const *this_str;
3230 char const *other_str;
3231 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3232 decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
3233 if (this_len != other_len)
3235 JSON_ASSERT(this_str && other_str);
3236 int comp = memcmp(this_str, other_str, this_len);
3241 return value_.map_->size() == other.value_.map_->size() &&
3242 (*value_.map_) == (*other.value_.map_);
3244 JSON_ASSERT_UNREACHABLE;
3246 return false; // unreachable
3249 bool Value::operator!=(const Value &other) const { return !(*this == other); }
3251 const char *Value::asCString() const
3253 JSON_ASSERT_MESSAGE(type_ == stringValue, "in Json::Value::asCString(): requires stringValue");
3254 if (value_.string_ == 0)
3257 char const *this_str;
3258 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3262 #if JSONCPP_USING_SECURE_MEMORY
3263 unsigned Value::getCStringLength() const
3265 JSON_ASSERT_MESSAGE(type_ == stringValue, "in Json::Value::asCString(): requires stringValue");
3266 if (value_.string_ == 0)
3269 char const *this_str;
3270 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3275 bool Value::getString(char const **str, char const **cend) const
3277 if (type_ != stringValue)
3279 if (value_.string_ == 0)
3282 decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
3283 *cend = *str + length;
3287 JSONCPP_STRING Value::asString() const
3295 if (value_.string_ == 0)
3298 char const *this_str;
3299 decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
3300 return JSONCPP_STRING(this_str, this_len);
3303 return value_.bool_ ? "true" : "false";
3305 return valueToString(value_.int_);
3307 return valueToString(value_.uint_);
3309 return valueToString(value_.real_);
3311 JSON_FAIL_MESSAGE("Type is not convertible to string");
3315 #ifdef JSON_USE_CPPTL
3316 CppTL::ConstString Value::asConstString() const
3320 decodePrefixedString(allocated_, value_.string_, &len, &str);
3321 return CppTL::ConstString(str, len);
3325 Value::Int Value::asInt() const
3330 JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
3331 return Int(value_.int_);
3333 JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
3334 return Int(value_.uint_);
3336 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt), "double out of Int range");
3337 return Int(value_.real_);
3341 return value_.bool_ ? 1 : 0;
3345 JSON_FAIL_MESSAGE("Value is not convertible to Int.");
3348 Value::UInt Value::asUInt() const
3353 JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
3354 return UInt(value_.int_);
3356 JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
3357 return UInt(value_.uint_);
3359 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt), "double out of UInt range");
3360 return UInt(value_.real_);
3364 return value_.bool_ ? 1 : 0;
3368 JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
3371 #if defined(JSON_HAS_INT64)
3373 Value::Int64 Value::asInt64() const
3378 return Int64(value_.int_);
3380 JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
3381 return Int64(value_.uint_);
3383 JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64), "double out of Int64 range");
3384 return Int64(value_.real_);
3388 return value_.bool_ ? 1 : 0;
3392 JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
3395 Value::UInt64 Value::asUInt64() const
3400 JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
3401 return UInt64(value_.int_);
3403 return UInt64(value_.uint_);
3405 JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64), "double out of UInt64 range");
3406 return UInt64(value_.real_);
3410 return value_.bool_ ? 1 : 0;
3414 JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
3416 #endif // if defined(JSON_HAS_INT64)
3418 LargestInt Value::asLargestInt() const
3420 #if defined(JSON_NO_INT64)
3427 LargestUInt Value::asLargestUInt() const
3429 #if defined(JSON_NO_INT64)
3436 double Value::asDouble() const
3441 return static_cast<double>(value_.int_);
3443 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3444 return static_cast<double>(value_.uint_);
3445 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3446 return integerToDouble(value_.uint_);
3447 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3449 return value_.real_;
3453 return value_.bool_ ? 1.0 : 0.0;
3457 JSON_FAIL_MESSAGE("Value is not convertible to double.");
3460 float Value::asFloat() const
3465 return static_cast<float>(value_.int_);
3467 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3468 return static_cast<float>(value_.uint_);
3469 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3470 // This can fail (silently?) if the value is bigger than MAX_FLOAT.
3471 return static_cast<float>(integerToDouble(value_.uint_));
3472 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3474 return static_cast<float>(value_.real_);
3478 return value_.bool_ ? 1.0f : 0.0f;
3482 JSON_FAIL_MESSAGE("Value is not convertible to float.");
3485 bool Value::asBool() const
3490 return value_.bool_;
3494 return value_.int_ ? true : false;
3496 return value_.uint_ ? true : false;
3498 // This is kind of strange. Not recommended.
3499 return (value_.real_ != 0.0) ? true : false;
3503 JSON_FAIL_MESSAGE("Value is not convertible to bool.");
3506 bool Value::isConvertibleTo(ValueType other) const
3511 return (isNumeric() && asDouble() == 0.0) ||
3512 (type_ == booleanValue && value_.bool_ == false) ||
3513 (type_ == stringValue && asString() == "") ||
3514 (type_ == arrayValue && value_.map_->size() == 0) ||
3515 (type_ == objectValue && value_.map_->size() == 0) || type_ == nullValue;
3517 return isInt() || (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
3518 type_ == booleanValue || type_ == nullValue;
3520 return isUInt() || (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
3521 type_ == booleanValue || type_ == nullValue;
3523 return isNumeric() || type_ == booleanValue || type_ == nullValue;
3525 return isNumeric() || type_ == booleanValue || type_ == nullValue;
3527 return isNumeric() || type_ == booleanValue || type_ == stringValue || type_ == nullValue;
3529 return type_ == arrayValue || type_ == nullValue;
3531 return type_ == objectValue || type_ == nullValue;
3533 JSON_ASSERT_UNREACHABLE;
3537 /// Number of values in array or object
3538 ArrayIndex Value::size() const
3549 case arrayValue: // size of the array is highest index + 1
3550 if (!value_.map_->empty())
3552 ObjectValues::const_iterator itLast = value_.map_->end();
3554 return (*itLast).first.index() + 1;
3558 return ArrayIndex(value_.map_->size());
3560 JSON_ASSERT_UNREACHABLE;
3561 return 0; // unreachable;
3564 bool Value::empty() const
3566 if (isNull() || isArray() || isObject())
3567 return size() == 0u;
3572 bool Value::operator!() const { return isNull(); }
3576 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || type_ == objectValue,
3577 "in Json::Value::clear(): requires complex value");
3584 value_.map_->clear();
3591 void Value::resize(ArrayIndex newSize)
3593 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3594 "in Json::Value::resize(): requires arrayValue");
3595 if (type_ == nullValue)
3596 *this = Value(arrayValue);
3597 ArrayIndex oldSize = size();
3600 else if (newSize > oldSize)
3601 (*this)[newSize - 1];
3604 for (ArrayIndex index = newSize; index < oldSize; ++index)
3606 value_.map_->erase(index);
3608 JSON_ASSERT(size() == newSize);
3612 Value &Value::operator[](ArrayIndex index)
3614 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3615 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
3616 if (type_ == nullValue)
3617 *this = Value(arrayValue);
3618 CZString key(index);
3619 ObjectValues::iterator it = value_.map_->lower_bound(key);
3620 if (it != value_.map_->end() && (*it).first == key)
3621 return (*it).second;
3623 ObjectValues::value_type defaultValue(key, nullSingleton());
3624 it = value_.map_->insert(it, defaultValue);
3625 return (*it).second;
3628 Value &Value::operator[](int index)
3630 JSON_ASSERT_MESSAGE(index >= 0,
3631 "in Json::Value::operator[](int index): index cannot be negative");
3632 return (*this)[ArrayIndex(index)];
3635 const Value &Value::operator[](ArrayIndex index) const
3637 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
3638 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
3639 if (type_ == nullValue)
3640 return nullSingleton();
3641 CZString key(index);
3642 ObjectValues::const_iterator it = value_.map_->find(key);
3643 if (it == value_.map_->end())
3644 return nullSingleton();
3645 return (*it).second;
3648 const Value &Value::operator[](int index) const
3650 JSON_ASSERT_MESSAGE(index >= 0,
3651 "in Json::Value::operator[](int index) const: index cannot be negative");
3652 return (*this)[ArrayIndex(index)];
3655 void Value::initBasic(ValueType vtype, bool allocated)
3658 allocated_ = allocated;
3664 // Access an object value by name, create a null member if it does not exist.
3665 // @pre Type of '*this' is object or null.
3666 // @param key is null-terminated.
3667 Value &Value::resolveReference(const char *key)
3669 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3670 "in Json::Value::resolveReference(): requires objectValue");
3671 if (type_ == nullValue)
3672 *this = Value(objectValue);
3673 CZString actualKey(key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
3674 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3675 if (it != value_.map_->end() && (*it).first == actualKey)
3676 return (*it).second;
3678 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3679 it = value_.map_->insert(it, defaultValue);
3680 Value &value = (*it).second;
3684 // @param key is not null-terminated.
3685 Value &Value::resolveReference(char const *key, char const *cend)
3687 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3688 "in Json::Value::resolveReference(key, end): requires objectValue");
3689 if (type_ == nullValue)
3690 *this = Value(objectValue);
3691 CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::duplicateOnCopy);
3692 ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
3693 if (it != value_.map_->end() && (*it).first == actualKey)
3694 return (*it).second;
3696 ObjectValues::value_type defaultValue(actualKey, nullSingleton());
3697 it = value_.map_->insert(it, defaultValue);
3698 Value &value = (*it).second;
3702 Value Value::get(ArrayIndex index, const Value &defaultValue) const
3704 const Value *value = &((*this)[index]);
3705 return value == &nullSingleton() ? defaultValue : *value;
3708 bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
3710 Value const *Value::find(char const *key, char const *cend) const
3712 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3713 "in Json::Value::find(key, end, found): requires objectValue or nullValue");
3714 if (type_ == nullValue)
3716 CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::noDuplication);
3717 ObjectValues::const_iterator it = value_.map_->find(actualKey);
3718 if (it == value_.map_->end())
3720 return &(*it).second;
3722 const Value &Value::operator[](const char *key) const
3724 Value const *found = find(key, key + strlen(key));
3726 return nullSingleton();
3729 Value const &Value::operator[](JSONCPP_STRING const &key) const
3731 Value const *found = find(key.data(), key.data() + key.length());
3733 return nullSingleton();
3737 Value &Value::operator[](const char *key) { return resolveReference(key, key + strlen(key)); }
3739 Value &Value::operator[](const JSONCPP_STRING &key)
3741 return resolveReference(key.data(), key.data() + key.length());
3744 Value &Value::operator[](const StaticString &key) { return resolveReference(key.c_str()); }
3746 #ifdef JSON_USE_CPPTL
3747 Value &Value::operator[](const CppTL::ConstString &key)
3749 return resolveReference(key.c_str(), key.end_c_str());
3751 Value const &Value::operator[](CppTL::ConstString const &key) const
3753 Value const *found = find(key.c_str(), key.end_c_str());
3755 return nullSingleton();
3760 Value &Value::append(const Value &value) { return (*this)[size()] = value; }
3762 Value Value::get(char const *key, char const *cend, Value const &defaultValue) const
3764 Value const *found = find(key, cend);
3765 return !found ? defaultValue : *found;
3767 Value Value::get(char const *key, Value const &defaultValue) const
3769 return get(key, key + strlen(key), defaultValue);
3771 Value Value::get(JSONCPP_STRING const &key, Value const &defaultValue) const
3773 return get(key.data(), key.data() + key.length(), defaultValue);
3776 bool Value::removeMember(const char *key, const char *cend, Value *removed)
3778 if (type_ != objectValue)
3782 CZString actualKey(key, static_cast<unsigned>(cend - key), CZString::noDuplication);
3783 ObjectValues::iterator it = value_.map_->find(actualKey);
3784 if (it == value_.map_->end())
3786 *removed = it->second;
3787 value_.map_->erase(it);
3790 bool Value::removeMember(const char *key, Value *removed)
3792 return removeMember(key, key + strlen(key), removed);
3794 bool Value::removeMember(JSONCPP_STRING const &key, Value *removed)
3796 return removeMember(key.data(), key.data() + key.length(), removed);
3798 Value Value::removeMember(const char *key)
3800 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3801 "in Json::Value::removeMember(): requires objectValue");
3802 if (type_ == nullValue)
3803 return nullSingleton();
3805 Value removed; // null
3806 removeMember(key, key + strlen(key), &removed);
3807 return removed; // still null if removeMember() did nothing
3809 Value Value::removeMember(const JSONCPP_STRING &key) { return removeMember(key.c_str()); }
3811 bool Value::removeIndex(ArrayIndex index, Value *removed)
3813 if (type_ != arrayValue)
3817 CZString key(index);
3818 ObjectValues::iterator it = value_.map_->find(key);
3819 if (it == value_.map_->end())
3823 *removed = it->second;
3824 ArrayIndex oldSize = size();
3825 // shift left all items left, into the place of the "removed"
3826 for (ArrayIndex i = index; i < (oldSize - 1); ++i)
3829 (*value_.map_)[keey] = (*this)[i + 1];
3831 // erase the last one ("leftover")
3832 CZString keyLast(oldSize - 1);
3833 ObjectValues::iterator itLast = value_.map_->find(keyLast);
3834 value_.map_->erase(itLast);
3838 #ifdef JSON_USE_CPPTL
3839 Value Value::get(const CppTL::ConstString &key, const Value &defaultValue) const
3841 return get(key.c_str(), key.end_c_str(), defaultValue);
3845 bool Value::isMember(char const *key, char const *cend) const
3847 Value const *value = find(key, cend);
3848 return NULL != value;
3850 bool Value::isMember(char const *key) const { return isMember(key, key + strlen(key)); }
3851 bool Value::isMember(JSONCPP_STRING const &key) const
3853 return isMember(key.data(), key.data() + key.length());
3856 #ifdef JSON_USE_CPPTL
3857 bool Value::isMember(const CppTL::ConstString &key) const
3859 return isMember(key.c_str(), key.end_c_str());
3863 Value::Members Value::getMemberNames() const
3865 JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
3866 "in Json::Value::getMemberNames(), value must be objectValue");
3867 if (type_ == nullValue)
3868 return Value::Members();
3870 members.reserve(value_.map_->size());
3871 ObjectValues::const_iterator it = value_.map_->begin();
3872 ObjectValues::const_iterator itEnd = value_.map_->end();
3873 for (; it != itEnd; ++it)
3875 members.push_back(JSONCPP_STRING((*it).first.data(), (*it).first.length()));
3880 //# ifdef JSON_USE_CPPTL
3882 // Value::enumMemberNames() const
3884 // if ( type_ == objectValue )
3886 // return CppTL::Enum::any( CppTL::Enum::transform(
3887 // CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
3888 // MemberNamesTransform() ) );
3890 // return EnumMemberNames();
3895 // Value::enumValues() const
3897 // if ( type_ == objectValue || type_ == arrayValue )
3898 // return CppTL::Enum::anyValues( *(value_.map_),
3899 // CppTL::Type<const Value &>() );
3900 // return EnumValues();
3905 static bool IsIntegral(double d)
3907 double integral_part;
3908 return modf(d, &integral_part) == 0.0;
3911 bool Value::isNull() const { return type_ == nullValue; }
3913 bool Value::isBool() const { return type_ == booleanValue; }
3915 bool Value::isInt() const
3920 return value_.int_ >= minInt && value_.int_ <= maxInt;
3922 return value_.uint_ <= UInt(maxInt);
3924 return value_.real_ >= minInt && value_.real_ <= maxInt && IsIntegral(value_.real_);
3931 bool Value::isUInt() const
3936 return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
3938 return value_.uint_ <= maxUInt;
3940 return value_.real_ >= 0 && value_.real_ <= maxUInt && IsIntegral(value_.real_);
3947 bool Value::isInt64() const
3949 #if defined(JSON_HAS_INT64)
3955 return value_.uint_ <= UInt64(maxInt64);
3957 // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
3958 // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
3959 // require the value to be strictly less than the limit.
3960 return value_.real_ >= double(minInt64) && value_.real_ < double(maxInt64) &&
3961 IsIntegral(value_.real_);
3965 #endif // JSON_HAS_INT64
3969 bool Value::isUInt64() const
3971 #if defined(JSON_HAS_INT64)
3975 return value_.int_ >= 0;
3979 // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
3980 // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
3981 // require the value to be strictly less than the limit.
3982 return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
3986 #endif // JSON_HAS_INT64
3990 bool Value::isIntegral() const
3992 #if defined(JSON_HAS_INT64)
3993 return isInt64() || isUInt64();
3995 return isInt() || isUInt();
3999 bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
4001 bool Value::isNumeric() const { return isIntegral() || isDouble(); }
4003 bool Value::isString() const { return type_ == stringValue; }
4005 bool Value::isArray() const { return type_ == arrayValue; }
4007 bool Value::isObject() const { return type_ == objectValue; }
4009 void Value::setComment(const char *comment, size_t len, CommentPlacement placement)
4012 comments_ = new CommentInfo[numberOfCommentPlacement];
4013 if ((len > 0) && (comment[len - 1] == '\n'))
4015 // Always discard trailing newline, to aid indentation.
4018 comments_[placement].setComment(comment, len);
4021 void Value::setComment(const char *comment, CommentPlacement placement)
4023 setComment(comment, strlen(comment), placement);
4026 void Value::setComment(const JSONCPP_STRING &comment, CommentPlacement placement)
4028 setComment(comment.c_str(), comment.length(), placement);
4031 bool Value::hasComment(CommentPlacement placement) const
4033 return comments_ != 0 && comments_[placement].comment_ != 0;
4036 JSONCPP_STRING Value::getComment(CommentPlacement placement) const
4038 if (hasComment(placement))
4039 return comments_[placement].comment_;
4043 void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
4045 void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
4047 ptrdiff_t Value::getOffsetStart() const { return start_; }
4049 ptrdiff_t Value::getOffsetLimit() const { return limit_; }
4051 JSONCPP_STRING Value::toStyledString() const
4053 StyledWriter writer;
4054 return writer.write(*this);
4057 Value::const_iterator Value::begin() const
4064 return const_iterator(value_.map_->begin());
4069 return const_iterator();
4072 Value::const_iterator Value::end() const
4079 return const_iterator(value_.map_->end());
4084 return const_iterator();
4087 Value::iterator Value::begin()
4094 return iterator(value_.map_->begin());
4102 Value::iterator Value::end()
4109 return iterator(value_.map_->end());
4117 // class PathArgument
4118 // //////////////////////////////////////////////////////////////////
4120 PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
4122 PathArgument::PathArgument(ArrayIndex index) : key_(), index_(index), kind_(kindIndex) {}
4124 PathArgument::PathArgument(const char *key) : key_(key), index_(), kind_(kindKey) {}
4126 PathArgument::PathArgument(const JSONCPP_STRING &key) : key_(key.c_str()), index_(), kind_(kindKey)
4131 // //////////////////////////////////////////////////////////////////
4133 Path::Path(const JSONCPP_STRING &path, const PathArgument &a1, const PathArgument &a2,
4134 const PathArgument &a3, const PathArgument &a4, const PathArgument &a5)
4145 void Path::makePath(const JSONCPP_STRING &path, const InArgs &in)
4147 const char *current = path.c_str();
4148 const char *end = current + path.length();
4149 InArgs::const_iterator itInArg = in.begin();
4150 while (current != end)
4152 if (*current == '[')
4155 if (*current == '%')
4156 addPathInArg(path, in, itInArg, PathArgument::kindIndex);
4159 ArrayIndex index = 0;
4160 for (; current != end && *current >= '0' && *current <= '9'; ++current)
4161 index = index * 10 + ArrayIndex(*current - '0');
4162 args_.push_back(index);
4164 if (current == end || *++current != ']')
4165 invalidPath(path, int(current - path.c_str()));
4167 else if (*current == '%')
4169 addPathInArg(path, in, itInArg, PathArgument::kindKey);
4172 else if (*current == '.' || *current == ']')
4178 const char *beginName = current;
4179 while (current != end && !strchr("[.", *current))
4181 args_.push_back(JSONCPP_STRING(beginName, current));
4186 void Path::addPathInArg(const JSONCPP_STRING & /*path*/, const InArgs &in,
4187 InArgs::const_iterator &itInArg, PathArgument::Kind kind)
4189 if (itInArg == in.end())
4191 // Error: missing argument %d
4193 else if ((*itInArg)->kind_ != kind)
4195 // Error: bad argument type
4199 args_.push_back(**itInArg++);
4203 void Path::invalidPath(const JSONCPP_STRING & /*path*/, int /*location*/)
4205 // Error: invalid path.
4208 const Value &Path::resolve(const Value &root) const
4210 const Value *node = &root;
4211 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
4213 const PathArgument &arg = *it;
4214 if (arg.kind_ == PathArgument::kindIndex)
4216 if (!node->isArray() || !node->isValidIndex(arg.index_))
4218 // Error: unable to resolve path (array value expected at position...
4221 node = &((*node)[arg.index_]);
4223 else if (arg.kind_ == PathArgument::kindKey)
4225 if (!node->isObject())
4227 // Error: unable to resolve path (object value expected at position...)
4230 node = &((*node)[arg.key_]);
4231 if (node == &Value::nullSingleton())
4233 // Error: unable to resolve path (object has no member named '' at
4242 Value Path::resolve(const Value &root, const Value &defaultValue) const
4244 const Value *node = &root;
4245 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
4247 const PathArgument &arg = *it;
4248 if (arg.kind_ == PathArgument::kindIndex)
4250 if (!node->isArray() || !node->isValidIndex(arg.index_))
4251 return defaultValue;
4252 node = &((*node)[arg.index_]);
4254 else if (arg.kind_ == PathArgument::kindKey)
4256 if (!node->isObject())
4257 return defaultValue;
4258 node = &((*node)[arg.key_]);
4259 if (node == &Value::nullSingleton())
4260 return defaultValue;
4266 Value &Path::make(Value &root) const
4268 Value *node = &root;
4269 for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it)
4271 const PathArgument &arg = *it;
4272 if (arg.kind_ == PathArgument::kindIndex)
4274 if (!node->isArray())
4276 // Error: node is not an array at position ...
4278 node = &((*node)[arg.index_]);
4280 else if (arg.kind_ == PathArgument::kindKey)
4282 if (!node->isObject())
4284 // Error: node is not an object at position...
4286 node = &((*node)[arg.key_]);
4294 // //////////////////////////////////////////////////////////////////////
4295 // End of content of file: src/lib_json/json_value.cpp
4296 // //////////////////////////////////////////////////////////////////////
4298 // //////////////////////////////////////////////////////////////////////
4299 // Beginning of content of file: src/lib_json/json_writer.cpp
4300 // //////////////////////////////////////////////////////////////////////
4302 // Copyright 2011 Baptiste Lepilleur
4303 // Distributed under MIT license, or public domain if desired and
4304 // recognized in your jurisdiction.
4305 // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
4307 #if !defined(JSON_IS_AMALGAMATION)
4308 #include <json/writer.h>
4309 #include "json_tool.h"
4310 #endif // if !defined(JSON_IS_AMALGAMATION)
4320 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
4322 #define isfinite _finite
4323 #elif defined(__sun) && defined(__SVR4) // Solaris
4324 #if !defined(isfinite)
4326 #define isfinite finite
4329 #if !defined(isfinite)
4331 #define isfinite finite
4333 #elif defined(__hpux)
4334 #if !defined(isfinite)
4335 #if defined(__ia64) && !defined(finite)
4336 #define isfinite(x) ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
4339 #define isfinite finite
4344 #if !(defined(__QNXNTO__)) // QNX already defines isfinite
4345 #define isfinite std::isfinite
4349 #if defined(_MSC_VER)
4350 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
4351 #define snprintf sprintf_s
4352 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
4353 #define snprintf std::snprintf
4355 #define snprintf _snprintf
4357 #elif defined(__ANDROID__) || defined(__QNXNTO__)
4358 #define snprintf snprintf
4359 #elif __cplusplus >= 201103L
4360 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
4361 #define snprintf std::snprintf
4365 #if defined(__BORLANDC__)
4367 #define isfinite _finite
4368 #define snprintf _snprintf
4371 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
4372 // Disable warning about strdup being deprecated.
4373 #pragma warning(disable : 4996)
4379 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
4380 typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
4382 typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
4385 static bool containsControlCharacter(const char *str)
4389 if (isControlCharacter(*(str++)))
4395 static bool containsControlCharacter0(const char *str, unsigned len)
4397 char const *end = str + len;
4400 if (isControlCharacter(*str) || 0 == *str)
4407 JSONCPP_STRING valueToString(LargestInt value)
4409 UIntToStringBuffer buffer;
4410 char *current = buffer + sizeof(buffer);
4411 if (value == Value::minLargestInt)
4413 uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
4418 uintToString(LargestUInt(-value), current);
4423 uintToString(LargestUInt(value), current);
4425 assert(current >= buffer);
4429 JSONCPP_STRING valueToString(LargestUInt value)
4431 UIntToStringBuffer buffer;
4432 char *current = buffer + sizeof(buffer);
4433 uintToString(value, current);
4434 assert(current >= buffer);
4438 #if defined(JSON_HAS_INT64)
4440 JSONCPP_STRING valueToString(Int value) { return valueToString(LargestInt(value)); }
4442 JSONCPP_STRING valueToString(UInt value) { return valueToString(LargestUInt(value)); }
4444 #endif // # if defined(JSON_HAS_INT64)
4448 JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision)
4450 // Allocate a buffer that is more than large enough to store the 16 digits of
4451 // precision requested below.
4455 char formatString[6];
4456 sprintf(formatString, "%%.%dg", precision);
4458 // Print into the buffer. We need not request the alternative representation
4459 // that always has a decimal point because JSON doesn't distingish the
4460 // concepts of reals and integers.
4461 if (isfinite(value))
4463 len = snprintf(buffer, sizeof(buffer), formatString, value);
4467 // IEEE standard states that NaN values will not compare to themselves
4470 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
4474 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
4478 len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
4480 // For those, we do not need to call fixNumLoc, but it is fast.
4483 fixNumericLocale(buffer, buffer + len);
4488 JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
4490 JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
4492 JSONCPP_STRING valueToQuotedString(const char *value)
4496 // Not sure how to handle unicode...
4497 if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL && !containsControlCharacter(value))
4498 return JSONCPP_STRING("\"") + value + "\"";
4499 // We have to walk value and escape any special characters.
4500 // Appending to JSONCPP_STRING is not efficient, but this should be rare.
4501 // (Note: forward slashes are *not* rare, but I am not escaping them.)
4502 JSONCPP_STRING::size_type maxsize = strlen(value) * 2 + 3; // allescaped+quotes+NULL
4503 JSONCPP_STRING result;
4504 result.reserve(maxsize); // to avoid lots of mallocs
4506 for (const char *c = value; *c != 0; ++c)
4532 // Even though \/ is considered a legal escape in JSON, a bare
4533 // slash is also legal, so I see no reason to escape it.
4534 // (I hope I am not misunderstanding something.
4535 // blep notes: actually escaping \/ may be useful in javascript to avoid </
4537 // Should add a flag to allow this compatibility mode and prevent this
4538 // sequence from occurring.
4540 if (isControlCharacter(*c))
4542 JSONCPP_OSTRINGSTREAM oss;
4543 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4)
4544 << static_cast<int>(*c);
4545 result += oss.str();
4558 // https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
4559 static char const *strnpbrk(char const *s, char const *accept, size_t n)
4561 assert((s || !n) && accept);
4563 char const *const end = s + n;
4564 for (char const *cur = s; cur < end; ++cur)
4567 for (char const *a = accept; *a; ++a)
4577 static JSONCPP_STRING valueToQuotedStringN(const char *value, unsigned length)
4581 // Not sure how to handle unicode...
4582 if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
4583 !containsControlCharacter0(value, length))
4584 return JSONCPP_STRING("\"") + value + "\"";
4585 // We have to walk value and escape any special characters.
4586 // Appending to JSONCPP_STRING is not efficient, but this should be rare.
4587 // (Note: forward slashes are *not* rare, but I am not escaping them.)
4588 JSONCPP_STRING::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
4589 JSONCPP_STRING result;
4590 result.reserve(maxsize); // to avoid lots of mallocs
4592 char const *end = value + length;
4593 for (const char *c = value; c != end; ++c)
4619 // Even though \/ is considered a legal escape in JSON, a bare
4620 // slash is also legal, so I see no reason to escape it.
4621 // (I hope I am not misunderstanding something.)
4622 // blep notes: actually escaping \/ may be useful in javascript to avoid </
4624 // Should add a flag to allow this compatibility mode and prevent this
4625 // sequence from occurring.
4627 if ((isControlCharacter(*c)) || (*c == 0))
4629 JSONCPP_OSTRINGSTREAM oss;
4630 oss << "\\u" << std::hex << std::uppercase << std::setfill('0') << std::setw(4)
4631 << static_cast<int>(*c);
4632 result += oss.str();
4646 // //////////////////////////////////////////////////////////////////
4647 Writer::~Writer() {}
4650 // //////////////////////////////////////////////////////////////////
4652 FastWriter::FastWriter()
4653 : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), omitEndingLineFeed_(false)
4657 void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
4659 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
4661 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
4663 JSONCPP_STRING FastWriter::write(const Value &root)
4667 if (!omitEndingLineFeed_)
4672 void FastWriter::writeValue(const Value &value)
4674 switch (value.type())
4677 if (!dropNullPlaceholders_)
4678 document_ += "null";
4681 document_ += valueToString(value.asLargestInt());
4684 document_ += valueToString(value.asLargestUInt());
4687 document_ += valueToString(value.asDouble());
4691 // Is NULL possible for value.string_? No.
4694 bool ok = value.getString(&str, &end);
4696 document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
4700 document_ += valueToString(value.asBool());
4705 ArrayIndex size = value.size();
4706 for (ArrayIndex index = 0; index < size; ++index)
4710 writeValue(value[index]);
4717 Value::Members members(value.getMemberNames());
4719 for (Value::Members::iterator it = members.begin(); it != members.end(); ++it)
4721 const JSONCPP_STRING &name = *it;
4722 if (it != members.begin())
4724 document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
4725 document_ += yamlCompatiblityEnabled_ ? ": " : ":";
4726 writeValue(value[name]);
4734 // Class StyledWriter
4735 // //////////////////////////////////////////////////////////////////
4737 StyledWriter::StyledWriter() : rightMargin_(74), indentSize_(3), addChildValues_() {}
4739 JSONCPP_STRING StyledWriter::write(const Value &root)
4742 addChildValues_ = false;
4744 writeCommentBeforeValue(root);
4746 writeCommentAfterValueOnSameLine(root);
4751 void StyledWriter::writeValue(const Value &value)
4753 switch (value.type())
4759 pushValue(valueToString(value.asLargestInt()));
4762 pushValue(valueToString(value.asLargestUInt()));
4765 pushValue(valueToString(value.asDouble()));
4769 // Is NULL possible for value.string_? No.
4772 bool ok = value.getString(&str, &end);
4774 pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
4780 pushValue(valueToString(value.asBool()));
4783 writeArrayValue(value);
4787 Value::Members members(value.getMemberNames());
4788 if (members.empty())
4792 writeWithIndent("{");
4794 Value::Members::iterator it = members.begin();
4797 const JSONCPP_STRING &name = *it;
4798 const Value &childValue = value[name];
4799 writeCommentBeforeValue(childValue);
4800 writeWithIndent(valueToQuotedString(name.c_str()));
4802 writeValue(childValue);
4803 if (++it == members.end())
4805 writeCommentAfterValueOnSameLine(childValue);
4809 writeCommentAfterValueOnSameLine(childValue);
4812 writeWithIndent("}");
4819 void StyledWriter::writeArrayValue(const Value &value)
4821 unsigned size = value.size();
4826 bool isArrayMultiLine = isMultineArray(value);
4827 if (isArrayMultiLine)
4829 writeWithIndent("[");
4831 bool hasChildValue = !childValues_.empty();
4835 const Value &childValue = value[index];
4836 writeCommentBeforeValue(childValue);
4838 writeWithIndent(childValues_[index]);
4842 writeValue(childValue);
4844 if (++index == size)
4846 writeCommentAfterValueOnSameLine(childValue);
4850 writeCommentAfterValueOnSameLine(childValue);
4853 writeWithIndent("]");
4855 else // output on a single line
4857 assert(childValues_.size() == size);
4859 for (unsigned index = 0; index < size; ++index)
4863 document_ += childValues_[index];
4870 bool StyledWriter::isMultineArray(const Value &value)
4872 ArrayIndex const size = value.size();
4873 bool isMultiLine = size * 3 >= rightMargin_;
4874 childValues_.clear();
4875 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
4877 const Value &childValue = value[index];
4878 isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
4880 if (!isMultiLine) // check if line length > max line length
4882 childValues_.reserve(size);
4883 addChildValues_ = true;
4884 ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
4885 for (ArrayIndex index = 0; index < size; ++index)
4887 if (hasCommentForValue(value[index]))
4891 writeValue(value[index]);
4892 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
4894 addChildValues_ = false;
4895 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4900 void StyledWriter::pushValue(const JSONCPP_STRING &value)
4902 if (addChildValues_)
4903 childValues_.push_back(value);
4908 void StyledWriter::writeIndent()
4910 if (!document_.empty())
4912 char last = document_[document_.length() - 1];
4913 if (last == ' ') // already indented
4915 if (last != '\n') // Comments may add new-line
4918 document_ += indentString_;
4921 void StyledWriter::writeWithIndent(const JSONCPP_STRING &value)
4927 void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
4929 void StyledWriter::unindent()
4931 assert(indentString_.size() >= indentSize_);
4932 indentString_.resize(indentString_.size() - indentSize_);
4935 void StyledWriter::writeCommentBeforeValue(const Value &root)
4937 if (!root.hasComment(commentBefore))
4942 const JSONCPP_STRING &comment = root.getComment(commentBefore);
4943 JSONCPP_STRING::const_iterator iter = comment.begin();
4944 while (iter != comment.end())
4947 if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
4952 // Comments are stripped of trailing newlines, so add one here
4956 void StyledWriter::writeCommentAfterValueOnSameLine(const Value &root)
4958 if (root.hasComment(commentAfterOnSameLine))
4959 document_ += " " + root.getComment(commentAfterOnSameLine);
4961 if (root.hasComment(commentAfter))
4964 document_ += root.getComment(commentAfter);
4969 bool StyledWriter::hasCommentForValue(const Value &value)
4971 return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) ||
4972 value.hasComment(commentAfter);
4975 // Class StyledStreamWriter
4976 // //////////////////////////////////////////////////////////////////
4978 StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
4979 : document_(NULL), rightMargin_(74), indentation_(indentation), addChildValues_()
4983 void StyledStreamWriter::write(JSONCPP_OSTREAM &out, const Value &root)
4986 addChildValues_ = false;
4989 writeCommentBeforeValue(root);
4994 writeCommentAfterValueOnSameLine(root);
4996 document_ = NULL; // Forget the stream, for safety.
4999 void StyledStreamWriter::writeValue(const Value &value)
5001 switch (value.type())
5007 pushValue(valueToString(value.asLargestInt()));
5010 pushValue(valueToString(value.asLargestUInt()));
5013 pushValue(valueToString(value.asDouble()));
5017 // Is NULL possible for value.string_? No.
5020 bool ok = value.getString(&str, &end);
5022 pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
5028 pushValue(valueToString(value.asBool()));
5031 writeArrayValue(value);
5035 Value::Members members(value.getMemberNames());
5036 if (members.empty())
5040 writeWithIndent("{");
5042 Value::Members::iterator it = members.begin();
5045 const JSONCPP_STRING &name = *it;
5046 const Value &childValue = value[name];
5047 writeCommentBeforeValue(childValue);
5048 writeWithIndent(valueToQuotedString(name.c_str()));
5049 *document_ << " : ";
5050 writeValue(childValue);
5051 if (++it == members.end())
5053 writeCommentAfterValueOnSameLine(childValue);
5057 writeCommentAfterValueOnSameLine(childValue);
5060 writeWithIndent("}");
5067 void StyledStreamWriter::writeArrayValue(const Value &value)
5069 unsigned size = value.size();
5074 bool isArrayMultiLine = isMultineArray(value);
5075 if (isArrayMultiLine)
5077 writeWithIndent("[");
5079 bool hasChildValue = !childValues_.empty();
5083 const Value &childValue = value[index];
5084 writeCommentBeforeValue(childValue);
5086 writeWithIndent(childValues_[index]);
5092 writeValue(childValue);
5095 if (++index == size)
5097 writeCommentAfterValueOnSameLine(childValue);
5101 writeCommentAfterValueOnSameLine(childValue);
5104 writeWithIndent("]");
5106 else // output on a single line
5108 assert(childValues_.size() == size);
5110 for (unsigned index = 0; index < size; ++index)
5114 *document_ << childValues_[index];
5121 bool StyledStreamWriter::isMultineArray(const Value &value)
5123 ArrayIndex const size = value.size();
5124 bool isMultiLine = size * 3 >= rightMargin_;
5125 childValues_.clear();
5126 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
5128 const Value &childValue = value[index];
5129 isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
5131 if (!isMultiLine) // check if line length > max line length
5133 childValues_.reserve(size);
5134 addChildValues_ = true;
5135 ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
5136 for (ArrayIndex index = 0; index < size; ++index)
5138 if (hasCommentForValue(value[index]))
5142 writeValue(value[index]);
5143 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
5145 addChildValues_ = false;
5146 isMultiLine = isMultiLine || lineLength >= rightMargin_;
5151 void StyledStreamWriter::pushValue(const JSONCPP_STRING &value)
5153 if (addChildValues_)
5154 childValues_.push_back(value);
5156 *document_ << value;
5159 void StyledStreamWriter::writeIndent()
5161 // blep intended this to look at the so-far-written string
5162 // to determine whether we are already indented, but
5163 // with a stream we cannot do that. So we rely on some saved state.
5164 // The caller checks indented_.
5165 *document_ << '\n' << indentString_;
5168 void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING &value)
5172 *document_ << value;
5176 void StyledStreamWriter::indent() { indentString_ += indentation_; }
5178 void StyledStreamWriter::unindent()
5180 assert(indentString_.size() >= indentation_.size());
5181 indentString_.resize(indentString_.size() - indentation_.size());
5184 void StyledStreamWriter::writeCommentBeforeValue(const Value &root)
5186 if (!root.hasComment(commentBefore))
5191 const JSONCPP_STRING &comment = root.getComment(commentBefore);
5192 JSONCPP_STRING::const_iterator iter = comment.begin();
5193 while (iter != comment.end())
5195 *document_ << *iter;
5196 if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
5197 // writeIndent(); // would include newline
5198 *document_ << indentString_;
5204 void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value &root)
5206 if (root.hasComment(commentAfterOnSameLine))
5207 *document_ << ' ' << root.getComment(commentAfterOnSameLine);
5209 if (root.hasComment(commentAfter))
5212 *document_ << root.getComment(commentAfter);
5217 bool StyledStreamWriter::hasCommentForValue(const Value &value)
5219 return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) ||
5220 value.hasComment(commentAfter);
5223 //////////////////////////
5224 // BuiltStyledStreamWriter
5226 /// Scoped enums are not available until C++11.
5229 /// Decide whether to write comments.
5232 None, ///< Drop all comments.
5233 Most, ///< Recover odd behavior of previous versions (not implemented yet).
5234 All ///< Keep all comments.
5238 struct BuiltStyledStreamWriter : public StreamWriter
5240 BuiltStyledStreamWriter(JSONCPP_STRING const &indentation, CommentStyle::Enum cs,
5241 JSONCPP_STRING const &colonSymbol, JSONCPP_STRING const &nullSymbol,
5242 JSONCPP_STRING const &endingLineFeedSymbol, bool useSpecialFloats,
5243 unsigned int precision);
5244 int write(Value const &root, JSONCPP_OSTREAM *sout) JSONCPP_OVERRIDE;
5247 void writeValue(Value const &value);
5248 void writeArrayValue(Value const &value);
5249 bool isMultineArray(Value const &value);
5250 void pushValue(JSONCPP_STRING const &value);
5252 void writeWithIndent(JSONCPP_STRING const &value);
5255 void writeCommentBeforeValue(Value const &root);
5256 void writeCommentAfterValueOnSameLine(Value const &root);
5257 static bool hasCommentForValue(const Value &value);
5259 typedef std::vector<JSONCPP_STRING> ChildValues;
5261 ChildValues childValues_;
5262 JSONCPP_STRING indentString_;
5263 unsigned int rightMargin_;
5264 JSONCPP_STRING indentation_;
5265 CommentStyle::Enum cs_;
5266 JSONCPP_STRING colonSymbol_;
5267 JSONCPP_STRING nullSymbol_;
5268 JSONCPP_STRING endingLineFeedSymbol_;
5269 bool addChildValues_ : 1;
5271 bool useSpecialFloats_ : 1;
5272 unsigned int precision_;
5274 BuiltStyledStreamWriter::BuiltStyledStreamWriter(JSONCPP_STRING const &indentation,
5275 CommentStyle::Enum cs,
5276 JSONCPP_STRING const &colonSymbol,
5277 JSONCPP_STRING const &nullSymbol,
5278 JSONCPP_STRING const &endingLineFeedSymbol,
5279 bool useSpecialFloats, unsigned int precision)
5280 : rightMargin_(74), indentation_(indentation), cs_(cs), colonSymbol_(colonSymbol),
5281 nullSymbol_(nullSymbol), endingLineFeedSymbol_(endingLineFeedSymbol), addChildValues_(false),
5282 indented_(false), useSpecialFloats_(useSpecialFloats), precision_(precision)
5285 int BuiltStyledStreamWriter::write(Value const &root, JSONCPP_OSTREAM *sout)
5288 addChildValues_ = false;
5291 writeCommentBeforeValue(root);
5296 writeCommentAfterValueOnSameLine(root);
5297 *sout_ << endingLineFeedSymbol_;
5301 void BuiltStyledStreamWriter::writeValue(Value const &value)
5303 switch (value.type())
5306 pushValue(nullSymbol_);
5309 pushValue(valueToString(value.asLargestInt()));
5312 pushValue(valueToString(value.asLargestUInt()));
5315 pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
5319 // Is NULL is possible for value.string_? No.
5322 bool ok = value.getString(&str, &end);
5324 pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
5330 pushValue(valueToString(value.asBool()));
5333 writeArrayValue(value);
5337 Value::Members members(value.getMemberNames());
5338 if (members.empty())
5342 writeWithIndent("{");
5344 Value::Members::iterator it = members.begin();
5347 JSONCPP_STRING const &name = *it;
5348 Value const &childValue = value[name];
5349 writeCommentBeforeValue(childValue);
5350 writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
5351 *sout_ << colonSymbol_;
5352 writeValue(childValue);
5353 if (++it == members.end())
5355 writeCommentAfterValueOnSameLine(childValue);
5359 writeCommentAfterValueOnSameLine(childValue);
5362 writeWithIndent("}");
5369 void BuiltStyledStreamWriter::writeArrayValue(Value const &value)
5371 unsigned size = value.size();
5376 bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
5379 writeWithIndent("[");
5381 bool hasChildValue = !childValues_.empty();
5385 Value const &childValue = value[index];
5386 writeCommentBeforeValue(childValue);
5388 writeWithIndent(childValues_[index]);
5394 writeValue(childValue);
5397 if (++index == size)
5399 writeCommentAfterValueOnSameLine(childValue);
5403 writeCommentAfterValueOnSameLine(childValue);
5406 writeWithIndent("]");
5408 else // output on a single line
5410 assert(childValues_.size() == size);
5412 if (!indentation_.empty())
5414 for (unsigned index = 0; index < size; ++index)
5417 *sout_ << ((!indentation_.empty()) ? ", " : ",");
5418 *sout_ << childValues_[index];
5420 if (!indentation_.empty())
5427 bool BuiltStyledStreamWriter::isMultineArray(Value const &value)
5429 ArrayIndex const size = value.size();
5430 bool isMultiLine = size * 3 >= rightMargin_;
5431 childValues_.clear();
5432 for (ArrayIndex index = 0; index < size && !isMultiLine; ++index)
5434 Value const &childValue = value[index];
5435 isMultiLine = ((childValue.isArray() || childValue.isObject()) && childValue.size() > 0);
5437 if (!isMultiLine) // check if line length > max line length
5439 childValues_.reserve(size);
5440 addChildValues_ = true;
5441 ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
5442 for (ArrayIndex index = 0; index < size; ++index)
5444 if (hasCommentForValue(value[index]))
5448 writeValue(value[index]);
5449 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
5451 addChildValues_ = false;
5452 isMultiLine = isMultiLine || lineLength >= rightMargin_;
5457 void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const &value)
5459 if (addChildValues_)
5460 childValues_.push_back(value);
5465 void BuiltStyledStreamWriter::writeIndent()
5467 // blep intended this to look at the so-far-written string
5468 // to determine whether we are already indented, but
5469 // with a stream we cannot do that. So we rely on some saved state.
5470 // The caller checks indented_.
5472 if (!indentation_.empty())
5474 // In this case, drop newlines too.
5475 *sout_ << '\n' << indentString_;
5479 void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const &value)
5487 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
5489 void BuiltStyledStreamWriter::unindent()
5491 assert(indentString_.size() >= indentation_.size());
5492 indentString_.resize(indentString_.size() - indentation_.size());
5495 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const &root)
5497 if (cs_ == CommentStyle::None)
5499 if (!root.hasComment(commentBefore))
5504 const JSONCPP_STRING &comment = root.getComment(commentBefore);
5505 JSONCPP_STRING::const_iterator iter = comment.begin();
5506 while (iter != comment.end())
5509 if (*iter == '\n' && (iter != comment.end() && *(iter + 1) == '/'))
5510 // writeIndent(); // would write extra newline
5511 *sout_ << indentString_;
5517 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const &root)
5519 if (cs_ == CommentStyle::None)
5521 if (root.hasComment(commentAfterOnSameLine))
5522 *sout_ << " " + root.getComment(commentAfterOnSameLine);
5524 if (root.hasComment(commentAfter))
5527 *sout_ << root.getComment(commentAfter);
5532 bool BuiltStyledStreamWriter::hasCommentForValue(const Value &value)
5534 return value.hasComment(commentBefore) || value.hasComment(commentAfterOnSameLine) ||
5535 value.hasComment(commentAfter);
5541 StreamWriter::StreamWriter() : sout_(NULL) {}
5542 StreamWriter::~StreamWriter() {}
5543 StreamWriter::Factory::~Factory() {}
5544 StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
5545 StreamWriterBuilder::~StreamWriterBuilder() {}
5546 StreamWriter *StreamWriterBuilder::newStreamWriter() const
5548 JSONCPP_STRING indentation = settings_["indentation"].asString();
5549 JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
5550 bool eyc = settings_["enableYAMLCompatibility"].asBool();
5551 bool dnp = settings_["dropNullPlaceholders"].asBool();
5552 bool usf = settings_["useSpecialFloats"].asBool();
5553 unsigned int pre = settings_["precision"].asUInt();
5554 CommentStyle::Enum cs = CommentStyle::All;
5555 if (cs_str == "All")
5557 cs = CommentStyle::All;
5559 else if (cs_str == "None")
5561 cs = CommentStyle::None;
5565 throwRuntimeError("commentStyle must be 'All' or 'None'");
5567 JSONCPP_STRING colonSymbol = " : ";
5572 else if (indentation.empty())
5576 JSONCPP_STRING nullSymbol = "null";
5583 JSONCPP_STRING endingLineFeedSymbol = "";
5584 return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol, endingLineFeedSymbol,
5587 static void getValidWriterKeys(std::set<JSONCPP_STRING> *valid_keys)
5589 valid_keys->clear();
5590 valid_keys->insert("indentation");
5591 valid_keys->insert("commentStyle");
5592 valid_keys->insert("enableYAMLCompatibility");
5593 valid_keys->insert("dropNullPlaceholders");
5594 valid_keys->insert("useSpecialFloats");
5595 valid_keys->insert("precision");
5597 bool StreamWriterBuilder::validate(Json::Value *invalid) const
5599 Json::Value my_invalid;
5601 invalid = &my_invalid; // so we do not need to test for NULL
5602 Json::Value &inv = *invalid;
5603 std::set<JSONCPP_STRING> valid_keys;
5604 getValidWriterKeys(&valid_keys);
5605 Value::Members keys = settings_.getMemberNames();
5606 size_t n = keys.size();
5607 for (size_t i = 0; i < n; ++i)
5609 JSONCPP_STRING const &key = keys[i];
5610 if (valid_keys.find(key) == valid_keys.end())
5612 inv[key] = settings_[key];
5615 return 0u == inv.size();
5617 Value &StreamWriterBuilder::operator[](JSONCPP_STRING key) { return settings_[key]; }
5619 void StreamWriterBuilder::setDefaults(Json::Value *settings)
5621 //! [StreamWriterBuilderDefaults]
5622 (*settings)["commentStyle"] = "All";
5623 (*settings)["indentation"] = "\t";
5624 (*settings)["enableYAMLCompatibility"] = false;
5625 (*settings)["dropNullPlaceholders"] = false;
5626 (*settings)["useSpecialFloats"] = false;
5627 (*settings)["precision"] = 17;
5628 //! [StreamWriterBuilderDefaults]
5631 JSONCPP_STRING writeString(StreamWriter::Factory const &builder, Value const &root)
5633 JSONCPP_OSTRINGSTREAM sout;
5634 StreamWriterPtr const writer(builder.newStreamWriter());
5635 writer->write(root, &sout);
5639 JSONCPP_OSTREAM &operator<<(JSONCPP_OSTREAM &sout, Value const &root)
5641 StreamWriterBuilder builder;
5642 StreamWriterPtr const writer(builder.newStreamWriter());
5643 writer->write(root, &sout);
5649 // //////////////////////////////////////////////////////////////////////
5650 // End of content of file: src/lib_json/json_writer.cpp
5651 // //////////////////////////////////////////////////////////////////////