76 #include "third_party/jsoncpp/json.h"
78 #ifndef JSON_IS_AMALGAMATION
79 #error "Compile with -I PATH_TO_JSON_DIRECTORY"
92 #ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
93 #define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
111 result[0] =
static_cast<char>(cp);
112 }
else if (cp <= 0x7FF) {
114 result[1] =
static_cast<char>(0x80 | (0x3f & cp));
115 result[0] =
static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
116 }
else if (cp <= 0xFFFF) {
118 result[2] =
static_cast<char>(0x80 | (0x3f & cp));
119 result[1] =
static_cast<char>(0x80 | (0x3f & (cp >> 6)));
120 result[0] =
static_cast<char>(0xE0 | (0xf & (cp >> 12)));
121 }
else if (cp <= 0x10FFFF) {
123 result[3] =
static_cast<char>(0x80 | (0x3f & cp));
124 result[2] =
static_cast<char>(0x80 | (0x3f & (cp >> 6)));
125 result[1] =
static_cast<char>(0x80 | (0x3f & (cp >> 12)));
126 result[0] =
static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
152 *--current =
static_cast<signed char>(
value % 10U +
static_cast<unsigned>(
'0'));
154 }
while (
value != 0);
173 #endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
193 #if !defined(JSON_IS_AMALGAMATION)
194 #include <json/assertions.h>
195 #include <json/reader.h>
196 #include <json/value.h>
197 #include "json_tool.h"
198 #endif // if !defined(JSON_IS_AMALGAMATION)
209 #if defined(_MSC_VER)
210 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
211 #define snprintf sprintf_s
212 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
213 #define snprintf std::snprintf
215 #define snprintf _snprintf
217 #elif defined(__ANDROID__) || defined(__QNXNTO__)
218 #define snprintf snprintf
219 #elif __cplusplus >= 201103L
220 #define snprintf std::snprintf
223 #if defined(__QNXNTO__)
224 #define sscanf std::sscanf
227 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
229 #pragma warning(disable : 4996)
237 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
247 : allowComments_(
true), strictRoot_(
false),
248 allowDroppedNullPlaceholders_(
false), allowNumericKeys_(
false) {}
254 features.allowComments_ =
false;
255 features.strictRoot_ =
true;
256 features.allowDroppedNullPlaceholders_ =
false;
257 features.allowNumericKeys_ =
false;
276 lastValue_(), commentsBefore_(), features_(Features::
all()),
277 collectComments_() {}
279 Reader::Reader(
const Features& features)
281 lastValue_(), commentsBefore_(), features_(features), collectComments_() {
286 document_ = document;
287 const char*
begin = document_.c_str();
288 const char*
end =
begin + document_.length();
301 std::getline(sin, doc, (
char)EOF);
302 return parse(doc,
root, collectComments);
308 bool collectComments) {
309 if (!features_.allowComments_) {
310 collectComments =
false;
315 collectComments_ = collectComments;
319 commentsBefore_ =
"";
326 bool successful = readValue();
328 skipCommentTokens(token);
329 if (collectComments_ && !commentsBefore_.empty())
331 if (features_.strictRoot_) {
332 if (!
root.isArray() && !
root.isObject()) {
335 token.type_ = tokenError;
336 token.start_ = beginDoc;
339 "A valid JSON document must be either an array or an object value.",
347 bool Reader::readValue() {
356 skipCommentTokens(token);
357 bool successful =
true;
359 if (collectComments_ && !commentsBefore_.empty()) {
361 commentsBefore_ =
"";
364 switch (token.type_) {
365 case tokenObjectBegin:
366 successful = readObject(token);
367 currentValue().setOffsetLimit(
current_ - begin_);
369 case tokenArrayBegin:
370 successful = readArray(token);
371 currentValue().setOffsetLimit(
current_ - begin_);
374 successful = decodeNumber(token);
377 successful = decodeString(token);
382 currentValue().swapPayload(
v);
383 currentValue().setOffsetStart(token.start_ - begin_);
384 currentValue().setOffsetLimit(token.end_ - begin_);
390 currentValue().swapPayload(
v);
391 currentValue().setOffsetStart(token.start_ - begin_);
392 currentValue().setOffsetLimit(token.end_ - begin_);
398 currentValue().swapPayload(
v);
399 currentValue().setOffsetStart(token.start_ - begin_);
400 currentValue().setOffsetLimit(token.end_ - begin_);
403 case tokenArraySeparator:
406 if (features_.allowDroppedNullPlaceholders_) {
411 currentValue().swapPayload(
v);
412 currentValue().setOffsetStart(
current_ - begin_ - 1);
413 currentValue().setOffsetLimit(
current_ - begin_);
417 currentValue().setOffsetStart(token.start_ - begin_);
418 currentValue().setOffsetLimit(token.end_ - begin_);
419 return addError(
"Syntax error: value, object or array expected.", token);
422 if (collectComments_) {
424 lastValue_ = ¤tValue();
431 void Reader::skipCommentTokens(Token& token) {
432 if (features_.allowComments_) {
435 }
while (token.type_ == tokenComment);
441 bool Reader::readToken(Token& token) {
444 Char c = getNextChar();
448 token.type_ = tokenObjectBegin;
451 token.type_ = tokenObjectEnd;
454 token.type_ = tokenArrayBegin;
457 token.type_ = tokenArrayEnd;
460 token.type_ = tokenString;
464 token.type_ = tokenComment;
478 token.type_ = tokenNumber;
482 token.type_ = tokenTrue;
486 token.type_ = tokenFalse;
490 token.type_ = tokenNull;
494 token.type_ = tokenArraySeparator;
497 token.type_ = tokenMemberSeparator;
500 token.type_ = tokenEndOfStream;
507 token.type_ = tokenError;
512 void Reader::skipSpaces() {
515 if (
c ==
' ' ||
c ==
'\t' ||
c ==
'\r' ||
c ==
'\n')
525 int index = patternLength;
533 bool Reader::readComment() {
534 Location commentBegin =
current_ - 1;
535 Char c = getNextChar();
536 bool successful =
false;
538 successful = readCStyleComment();
540 successful = readCppStyleComment();
544 if (collectComments_) {
551 addComment(commentBegin,
current_, placement);
559 Reader::Location current =
begin;
560 while (current !=
end) {
563 if (current !=
end && *current ==
'\n')
577 assert(collectComments_);
580 assert(lastValue_ != 0);
581 lastValue_->setComment(normalized, placement);
583 commentsBefore_ += normalized;
587 bool Reader::readCStyleComment() {
589 Char c = getNextChar();
593 return getNextChar() ==
'/';
596 bool Reader::readCppStyleComment() {
598 Char c = getNextChar();
612 void Reader::readNumber() {
616 while (
c >=
'0' &&
c <=
'9')
621 while (
c >=
'0' &&
c <=
'9')
625 if (
c ==
'e' ||
c ==
'E') {
627 if (
c ==
'+' ||
c ==
'-')
629 while (
c >=
'0' &&
c <=
'9')
634 bool Reader::readString() {
646 bool Reader::readObject(Token& tokenStart) {
650 currentValue().swapPayload(
init);
651 currentValue().setOffsetStart(tokenStart.start_ - begin_);
652 while (readToken(tokenName)) {
653 bool initialTokenOk =
true;
654 while (tokenName.type_ == tokenComment && initialTokenOk)
655 initialTokenOk = readToken(tokenName);
658 if (tokenName.type_ == tokenObjectEnd &&
name.empty())
661 if (tokenName.type_ == tokenString) {
662 if (!decodeString(tokenName,
name))
663 return recoverFromError(tokenObjectEnd);
664 }
else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
666 if (!decodeNumber(tokenName, numberName))
667 return recoverFromError(tokenObjectEnd);
668 name = numberName.asString();
674 if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
675 return addErrorAndRecover(
676 "Missing ':' after object member name", colon, tokenObjectEnd);
680 bool ok = readValue();
683 return recoverFromError(tokenObjectEnd);
686 if (!readToken(comma) ||
687 (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
688 comma.type_ != tokenComment)) {
689 return addErrorAndRecover(
690 "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
692 bool finalizeTokenOk =
true;
693 while (comma.type_ == tokenComment && finalizeTokenOk)
694 finalizeTokenOk = readToken(comma);
695 if (comma.type_ == tokenObjectEnd)
698 return addErrorAndRecover(
699 "Missing '}' or object member name", tokenName, tokenObjectEnd);
702 bool Reader::readArray(Token& tokenStart) {
704 currentValue().swapPayload(
init);
705 currentValue().setOffsetStart(tokenStart.start_ - begin_);
717 bool ok = readValue();
720 return recoverFromError(tokenArrayEnd);
724 ok = readToken(token);
725 while (token.type_ == tokenComment &&
ok) {
726 ok = readToken(token);
729 (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
730 if (!
ok || badTokenType) {
731 return addErrorAndRecover(
732 "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
734 if (token.type_ == tokenArrayEnd)
740 bool Reader::decodeNumber(Token& token) {
742 if (!decodeNumber(token, decoded))
744 currentValue().swapPayload(decoded);
745 currentValue().setOffsetStart(token.start_ - begin_);
746 currentValue().setOffsetLimit(token.end_ - begin_);
750 bool Reader::decodeNumber(Token& token,
Value& decoded) {
754 Location current = token.start_;
755 bool isNegative = *current ==
'-';
761 : Value::maxLargestUInt;
764 while (current < token.end_) {
766 if (c < '0' || c >
'9')
767 return decodeDouble(token, decoded);
769 if (
value >= threshold) {
774 if (
value > threshold || current != token.end_ ||
775 digit > maxIntegerValue % 10) {
776 return decodeDouble(token, decoded);
781 if (isNegative &&
value == maxIntegerValue)
782 decoded = Value::minLargestInt;
792 bool Reader::decodeDouble(Token& token) {
794 if (!decodeDouble(token, decoded))
796 currentValue().swapPayload(decoded);
797 currentValue().setOffsetStart(token.start_ - begin_);
798 currentValue().setOffsetLimit(token.end_ - begin_);
802 bool Reader::decodeDouble(Token& token,
Value& decoded) {
805 std::istringstream is(
buffer);
807 return addError(
"'" +
std::string(token.start_, token.end_) +
808 "' is not a number.",
814 bool Reader::decodeString(Token& token) {
816 if (!decodeString(token, decoded_string))
818 Value decoded(decoded_string);
819 currentValue().swapPayload(decoded);
820 currentValue().setOffsetStart(token.start_ - begin_);
821 currentValue().setOffsetLimit(token.end_ - begin_);
825 bool Reader::decodeString(Token& token,
std::string& decoded) {
826 decoded.reserve(token.end_ - token.start_ - 2);
827 Location current = token.start_ + 1;
828 Location
end = token.end_ - 1;
829 while (current !=
end) {
833 else if (
c ==
'\\') {
835 return addError(
"Empty escape sequence in string", token, current);
864 if (!decodeUnicodeCodePoint(token, current,
end,
unicode))
869 return addError(
"Bad escape sequence in string", token, current);
878 bool Reader::decodeUnicodeCodePoint(Token& token,
883 if (!decodeUnicodeEscapeSequence(token, current,
end,
unicode))
887 if (
end - current < 6)
889 "additional six characters expected to parse unicode surrogate pair.",
892 unsigned int surrogatePair;
893 if (*(current++) ==
'\\' && *(current++) ==
'u') {
894 if (decodeUnicodeEscapeSequence(token, current,
end, surrogatePair)) {
895 unicode = 0x10000 + ((
unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
899 return addError(
"expecting another \\u token to begin the second half of "
900 "a unicode surrogate pair",
907 bool Reader::decodeUnicodeEscapeSequence(Token& token,
911 if (
end - current < 4)
913 "Bad unicode escape sequence in string: four digits expected.",
920 if (
c >=
'0' &&
c <=
'9')
922 else if (
c >=
'a' &&
c <=
'f')
924 else if (
c >=
'A' &&
c <=
'F')
928 "Bad unicode escape sequence in string: hexadecimal digit expected.",
945 bool Reader::recoverFromError(TokenType skipUntilToken) {
949 if (!readToken(
skip))
951 if (
skip.type_ == skipUntilToken ||
skip.type_ == tokenEndOfStream)
960 TokenType skipUntilToken) {
962 return recoverFromError(skipUntilToken);
965 Value& Reader::currentValue() {
return *(
nodes_.top()); }
973 void Reader::getLocationLineAndColumn(Location location,
976 Location current = begin_;
977 Location lastLineStart = current;
979 while (current < location && current !=
end_) {
982 if (*current ==
'\n')
984 lastLineStart = current;
986 }
else if (
c ==
'\n') {
987 lastLineStart = current;
992 column =
int(location - lastLineStart) + 1;
996 std::string Reader::getLocationLineAndColumn(Location location)
const {
998 getLocationLineAndColumn(location,
line, column);
999 char buffer[18 + 16 + 16 + 1];
1005 std::string Reader::getFormatedErrorMessages()
const {
1006 return getFormattedErrorMessages();
1009 std::string Reader::getFormattedErrorMessages()
const {
1011 for (Errors::const_iterator itError =
errors_.begin();
1014 const ErrorInfo&
error = *itError;
1016 "* " + getLocationLineAndColumn(
error.token_.start_) +
"\n";
1017 formattedMessage +=
" " +
error.message_ +
"\n";
1020 "See " + getLocationLineAndColumn(
error.extra_) +
" for detail.\n";
1022 return formattedMessage;
1025 std::vector<Reader::StructuredError> Reader::getStructuredErrors()
const {
1026 std::vector<Reader::StructuredError> allErrors;
1027 for (Errors::const_iterator itError =
errors_.begin();
1030 const ErrorInfo&
error = *itError;
1031 Reader::StructuredError structured;
1032 structured.offset_start =
error.token_.start_ - begin_;
1033 structured.offset_limit =
error.token_.end_ - begin_;
1034 structured.message =
error.message_;
1035 allErrors.push_back(structured);
1046 token.type_ = tokenError;
1047 token.start_ = begin_ +
value.getOffsetStart();
1048 token.end_ =
end_ +
value.getOffsetLimit();
1050 info.token_ = token;
1061 || extra.getOffsetLimit() >
length)
1064 token.type_ = tokenError;
1065 token.start_ = begin_ +
value.getOffsetStart();
1066 token.end_ = begin_ +
value.getOffsetLimit();
1068 info.token_ = token;
1070 info.extra_ = begin_ + extra.getOffsetStart();
1075 bool Reader::good()
const {
1082 static OurFeatures
all();
1083 bool allowComments_;
1085 bool allowDroppedNullPlaceholders_;
1086 bool allowNumericKeys_;
1087 bool allowSingleQuotes_;
1089 bool rejectDupKeys_;
1090 bool allowSpecialFloats_;
1106 typedef const Char* Location;
1108 size_t offset_start;
1109 size_t offset_limit;
1114 bool parse(
const char* beginDoc,
1117 bool collectComments =
true);
1119 std::vector<StructuredError> getStructuredErrors()
const;
1129 tokenEndOfStream = 0,
1142 tokenArraySeparator,
1143 tokenMemberSeparator,
1164 bool readToken(
Token& token);
1168 bool readCStyleComment();
1169 bool readCppStyleComment();
1171 bool readStringSingleQuote();
1172 bool readNumber(
bool checkInf);
1174 bool readObject(
Token& token);
1175 bool readArray(
Token& token);
1176 bool decodeNumber(
Token& token);
1177 bool decodeNumber(
Token& token,
Value& decoded);
1178 bool decodeString(
Token& token);
1180 bool decodeDouble(
Token& token);
1181 bool decodeDouble(
Token& token,
Value& decoded);
1182 bool decodeUnicodeCodePoint(
Token& token,
1186 bool decodeUnicodeEscapeSequence(
Token& token,
1191 bool recoverFromError(
TokenType skipUntilToken);
1195 void skipUntilSpace();
1196 Value& currentValue();
1199 getLocationLineAndColumn(Location location,
int&
line,
int& column)
const;
1200 std::string getLocationLineAndColumn(Location location)
const;
1202 void skipCommentTokens(
Token& token);
1211 Location lastValueEnd_;
1217 bool collectComments_;
1224 lastValue_(), commentsBefore_(),
1226 features_(features), collectComments_() {
1232 bool collectComments) {
1234 collectComments =
false;
1255 addError(
"Extra non-whitespace after JSON value.", token);
1262 if (!
root.isArray() && !
root.isObject()) {
1266 token.start_ = beginDoc;
1267 token.end_ = endDoc;
1269 "A valid JSON document must be either an array or an object value.",
1282 bool successful =
true;
1289 switch (token.type_) {
1330 Value v(std::numeric_limits<double>::quiet_NaN());
1338 Value v(std::numeric_limits<double>::infinity());
1346 Value v(-std::numeric_limits<double>::infinity());
1368 return addError(
"Syntax error: value, object or array expected.", token);
1493 if (c ==
' ' || c ==
'\t' || c ==
'\r' || c ==
'\n')
1503 int index = patternLength;
1514 bool successful =
false;
1573 if (checkInf && p !=
end_ && *p ==
'I') {
1579 while (c >=
'0' && c <=
'9')
1584 while (c >=
'0' && c <=
'9')
1588 if (c ==
'e' || c ==
'E') {
1590 if (c ==
'+' || c ==
'-')
1592 while (c >=
'0' && c <=
'9')
1629 bool initialTokenOk =
true;
1630 while (tokenName.type_ ==
tokenComment && initialTokenOk)
1632 if (!initialTokenOk)
1644 name = numberName.asString();
1672 "Missing ',' or '}' in object declaration", comma,
tokenObjectEnd);
1674 bool finalizeTokenOk =
true;
1712 if (!
ok || badTokenType) {
1714 "Missing ',' or ']' in array declaration", token,
tokenArrayEnd);
1737 bool isNegative = *current ==
'-';
1743 :
Value::maxLargestUInt;
1746 while (current < token.end_) {
1747 Char c = *current++;
1748 if (c < '0' || c >
'9')
1751 if (
value >= threshold) {
1756 if (
value > threshold || current != token.end_ ||
1757 digit > maxIntegerValue % 10) {
1784 const int bufferSize = 32;
1786 int length =
int(token.end_ - token.start_);
1790 return addError(
"Unable to parse token length", token);
1800 if (
length <= bufferSize) {
1812 "' is not a number.",
1822 Value decoded(decoded_string);
1830 decoded.reserve(token.end_ - token.start_ - 2);
1831 Location current = token.start_ + 1;
1833 while (current !=
end) {
1834 Char c = *current++;
1837 else if (c ==
'\\') {
1839 return addError(
"Empty escape sequence in string", token, current);
1873 return addError(
"Bad escape sequence in string", token, current);
1891 if (
end - current < 6)
1893 "additional six characters expected to parse unicode surrogate pair.",
1896 unsigned int surrogatePair;
1897 if (*(current++) ==
'\\' && *(current++) ==
'u') {
1899 unicode = 0x10000 + ((
unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
1903 return addError(
"expecting another \\u token to begin the second half of "
1904 "a unicode surrogate pair",
1915 if (
end - current < 4)
1917 "Bad unicode escape sequence in string: four digits expected.",
1922 Char c = *current++;
1924 if (c >=
'0' && c <=
'9')
1926 else if (c >=
'a' && c <=
'f')
1928 else if (c >=
'A' && c <=
'F')
1932 "Bad unicode escape sequence in string: hexadecimal digit expected.",
1942 info.token_ = token;
1944 info.extra_ = extra;
1964 TokenType skipUntilToken) {
1979 int& column)
const {
1983 while (current < location && current !=
end_) {
1984 Char c = *current++;
1986 if (*current ==
'\n')
1988 lastLineStart = current;
1990 }
else if (c ==
'\n') {
1991 lastLineStart = current;
1996 column =
int(location - lastLineStart) + 1;
2003 char buffer[18 + 16 + 16 + 1];
2010 for (Errors::const_iterator itError =
errors_.begin();
2013 const ErrorInfo&
error = *itError;
2016 formattedMessage +=
" " +
error.message_ +
"\n";
2021 return formattedMessage;
2025 std::vector<OurReader::StructuredError> allErrors;
2026 for (Errors::const_iterator itError =
errors_.begin();
2029 const ErrorInfo&
error = *itError;
2030 OurReader::StructuredError structured;
2031 structured.offset_start =
error.token_.start_ -
begin_;
2032 structured.offset_limit =
error.token_.end_ -
begin_;
2033 structured.message =
error.message_;
2034 allErrors.push_back(structured);
2047 token.end_ =
end_ +
value.getOffsetLimit();
2049 info.token_ = token;
2060 || extra.getOffsetLimit() >
length)
2067 info.token_ = token;
2069 info.extra_ =
begin_ + extra.getOffsetStart();
2079 class OurCharReader :
public CharReader {
2084 bool collectComments,
2090 char const* beginDoc,
char const* endDoc,
2112 features.allowDroppedNullPlaceholders_ =
settings_[
"allowDroppedNullPlaceholders"].
asBool();
2114 features.allowSingleQuotes_ =
settings_[
"allowSingleQuotes"].
asBool();
2118 features.allowSpecialFloats_ =
settings_[
"allowSpecialFloats"].
asBool();
2119 return new OurCharReader(collectComments, features);
2123 valid_keys->clear();
2124 valid_keys->insert(
"collectComments");
2125 valid_keys->insert(
"allowComments");
2126 valid_keys->insert(
"strictRoot");
2127 valid_keys->insert(
"allowDroppedNullPlaceholders");
2128 valid_keys->insert(
"allowNumericKeys");
2129 valid_keys->insert(
"allowSingleQuotes");
2130 valid_keys->insert(
"stackLimit");
2131 valid_keys->insert(
"failIfExtra");
2132 valid_keys->insert(
"rejectDupKeys");
2133 valid_keys->insert(
"allowSpecialFloats");
2140 std::set<std::string> valid_keys;
2143 size_t n =
keys.size();
2144 for (
size_t i = 0;
i <
n; ++
i) {
2146 if (valid_keys.find(
key) == valid_keys.end()) {
2150 return 0
u == inv.
size();
2160 (*settings)[
"allowComments"] =
false;
2161 (*settings)[
"strictRoot"] =
true;
2162 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
2163 (*settings)[
"allowNumericKeys"] =
false;
2164 (*settings)[
"allowSingleQuotes"] =
false;
2165 (*settings)[
"stackLimit"] = 1000;
2166 (*settings)[
"failIfExtra"] =
true;
2167 (*settings)[
"rejectDupKeys"] =
true;
2168 (*settings)[
"allowSpecialFloats"] =
false;
2175 (*settings)[
"collectComments"] =
true;
2176 (*settings)[
"allowComments"] =
true;
2177 (*settings)[
"strictRoot"] =
false;
2178 (*settings)[
"allowDroppedNullPlaceholders"] =
false;
2179 (*settings)[
"allowNumericKeys"] =
false;
2180 (*settings)[
"allowSingleQuotes"] =
false;
2181 (*settings)[
"stackLimit"] = 1000;
2182 (*settings)[
"failIfExtra"] =
false;
2183 (*settings)[
"rejectDupKeys"] =
false;
2184 (*settings)[
"allowSpecialFloats"] =
false;
2192 CharReader::Factory
const& fact, std::istream& sin,
2195 std::ostringstream ssin;
2196 ssin << sin.rdbuf();
2198 char const*
begin = doc.data();
2199 char const*
end =
begin + doc.size();
2206 CharReaderBuilder
b;
2211 "Error from reader: %s",
2255 ValueIteratorBase::ValueIteratorBase(
2259 Value& ValueIteratorBase::deref()
const {
2263 void ValueIteratorBase::increment() {
2267 void ValueIteratorBase::decrement() {
2271 ValueIteratorBase::difference_type
2272 ValueIteratorBase::computeDistance(
const SelfType& other)
const {
2273 #ifdef JSON_USE_CPPTL_SMALLMAP
2281 if (isNull_ && other.isNull_) {
2290 difference_type myDistance = 0;
2299 bool ValueIteratorBase::isEqual(
const SelfType& other)
const {
2301 return other.isNull_;
2308 isNull_ = other.isNull_;
2312 const Value::CZString czstring = (*current_).first;
2313 if (czstring.data()) {
2314 if (czstring.isStaticString())
2315 return Value(StaticString(czstring.data()));
2316 return Value(czstring.data(), czstring.data() + czstring.length());
2318 return Value(czstring.index());
2322 const Value::CZString czstring = (*current_).first;
2323 if (!czstring.data())
2324 return czstring.index();
2331 keey = memberName(&
end);
2336 char const* ValueIteratorBase::memberName()
const {
2337 const char* cname = (*current_).first.data();
2338 return cname ? cname :
"";
2341 char const* ValueIteratorBase::memberName(
char const**
end)
const {
2342 const char* cname = (*current_).first.data();
2347 *
end = cname + (*current_).first.length();
2359 ValueConstIterator::ValueConstIterator() {}
2361 ValueConstIterator::ValueConstIterator(
2363 : ValueIteratorBase(current) {}
2365 ValueConstIterator::ValueConstIterator(ValueIterator
const& other)
2366 : ValueIteratorBase(other) {}
2368 ValueConstIterator& ValueConstIterator::
2369 operator=(
const ValueIteratorBase& other) {
2382 ValueIterator::ValueIterator() {}
2385 : ValueIteratorBase(current) {}
2387 ValueIterator::ValueIterator(
const ValueConstIterator& other)
2388 : ValueIteratorBase(other) {
2392 ValueIterator::ValueIterator(
const ValueIterator& other)
2393 : ValueIteratorBase(other) {}
2395 ValueIterator& ValueIterator::operator=(
const SelfType& other) {
2420 #if !defined(JSON_IS_AMALGAMATION)
2421 #include <json/assertions.h>
2422 #include <json/value.h>
2423 #include <json/writer.h>
2424 #endif // if !defined(JSON_IS_AMALGAMATION)
2430 #ifdef JSON_USE_CPPTL
2431 #include <cpptl/conststring.h>
2434 #include <algorithm>
2436 #define JSON_ASSERT_UNREACHABLE assert(false)
2443 #if defined(__ARMEL__)
2444 #define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
2446 #define ALIGNAS(byte_alignment)
2456 #if defined(JSON_HAS_INT64)
2463 static const double maxUInt64AsDouble = 18446744073709551615.0;
2464 #endif // defined(JSON_HAS_INT64)
2469 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2470 template <
typename T,
typename U>
2472 return d >=
min && d <=
max;
2474 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2479 template <
typename T>
static inline double integerToDouble(
T value) {
2480 return static_cast<double>(
value);
2483 template <
typename T,
typename U>
2485 return d >= integerToDouble(
min) &&
d <= integerToDouble(
max);
2487 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
2503 char* newString =
static_cast<char*
>(malloc(
length + 1));
2504 if (newString == NULL) {
2506 "in Json::Value::duplicateStringValue(): "
2507 "Failed to allocate string value buffer");
2523 "in Json::Value::duplicateAndPrefixStringValue(): "
2524 "length too big for prefixing");
2525 unsigned actualLength =
length +
static_cast<unsigned>(
sizeof(unsigned)) + 1U;
2526 char* newString =
static_cast<char*
>(malloc(actualLength));
2527 if (newString == 0) {
2529 "in Json::Value::duplicateAndPrefixStringValue(): "
2530 "Failed to allocate string value buffer");
2532 *
reinterpret_cast<unsigned*
>(newString) =
length;
2534 newString[actualLength - 1U] = 0;
2538 bool isPrefixed,
char const* prefixed,
2542 *
length =
static_cast<unsigned>(strlen(prefixed));
2545 *
length = *
reinterpret_cast<unsigned const*
>(prefixed);
2546 *
value = prefixed +
sizeof(unsigned);
2562 #if !defined(JSON_IS_AMALGAMATION)
2564 #include "json_valueiterator.inl"
2565 #endif // if !defined(JSON_IS_AMALGAMATION)
2572 Exception::~Exception() throw()
2574 char const* Exception::what()
const throw()
2576 return msg_.c_str();
2586 throw RuntimeError(
msg);
2590 throw LogicError(
msg);
2601 Value::CommentInfo::CommentInfo() : comment_(0) {}
2603 Value::CommentInfo::~CommentInfo() {
2608 void Value::CommentInfo::setComment(
const char*
text,
size_t len) {
2616 "in Json::Value::setComment(): Comments must start with /");
2634 Value::CZString::CZString(
char const*
str,
unsigned ulength, DuplicationPolicy allocate)
2638 storage_.length_ = ulength & 0x3FFFFFFF;
2641 Value::CZString::CZString(
const CZString& other)
2642 : cstr_(other.
storage_.policy_ != noDuplication && other.cstr_ != 0
2646 ? (
static_cast<DuplicationPolicy
>(other.storage_.policy_) == noDuplication
2647 ? noDuplication : duplicate)
2648 :
static_cast<DuplicationPolicy
>(other.storage_.policy_));
2649 storage_.length_ = other.storage_.length_;
2652 #if JSON_HAS_RVALUE_REFERENCES
2653 Value::CZString::CZString(CZString&& other)
2655 other.cstr_ =
nullptr;
2659 Value::CZString::~CZString() {
2660 if (cstr_ &&
storage_.policy_ == duplicate)
2669 Value::CZString& Value::CZString::operator=(CZString other) {
2675 if (!cstr_)
return index_ < other.index_;
2678 unsigned this_len = this->
storage_.length_;
2679 unsigned other_len = other.storage_.length_;
2680 unsigned min_len =
std::min(this_len, other_len);
2681 int comp = memcmp(this->cstr_, other.cstr_, min_len);
2682 if (comp < 0)
return true;
2683 if (comp > 0)
return false;
2684 return (this_len < other_len);
2688 if (!cstr_)
return index_ == other.index_;
2691 unsigned this_len = this->
storage_.length_;
2692 unsigned other_len = other.storage_.length_;
2693 if (this_len != other_len)
return false;
2694 int comp = memcmp(this->cstr_, other.cstr_, this_len);
2703 bool Value::CZString::isStaticString()
const {
return storage_.policy_ == noDuplication; }
2734 value_.map_ =
new ObjectValues();
2753 #if defined(JSON_HAS_INT64)
2762 #endif // defined(JSON_HAS_INT64)
2774 Value::Value(
const char* beginValue,
const char* endValue) {
2788 value_.string_ =
const_cast<char*
>(
value.c_str());
2791 #ifdef JSON_USE_CPPTL
2806 comments_(0),
start_(other.
start_), limit_(other.limit_)
2817 if (other.value_.string_ && other.allocated_) {
2825 value_.string_ = other.value_.string_;
2831 value_.map_ =
new ObjectValues(*other.value_.map_);
2836 if (other.comments_) {
2839 const CommentInfo& otherComment = other.comments_[comment];
2840 if (otherComment.comment_)
2841 comments_[comment].setComment(
2842 otherComment.comment_, strlen(otherComment.comment_));
2847 #if JSON_HAS_RVALUE_REFERENCES
2884 void Value::swapPayload(
Value& other) {
2886 type_ = other.type_;
2889 int temp2 = allocated_;
2890 allocated_ = other.allocated_;
2891 other.allocated_ = temp2 & 0x1;
2912 int typeDelta =
type_ - other.type_;
2914 return typeDelta < 0 ?
true :
false;
2919 return value_.int_ < other.value_.int_;
2921 return value_.uint_ < other.value_.uint_;
2923 return value_.real_ < other.value_.real_;
2925 return value_.bool_ < other.value_.bool_;
2928 if ((
value_.string_ == 0) || (other.value_.string_ == 0)) {
2929 if (other.value_.string_)
return true;
2934 char const* this_str;
2935 char const* other_str;
2938 unsigned min_len =
std::min(this_len, other_len);
2939 int comp = memcmp(this_str, other_str, min_len);
2940 if (comp < 0)
return true;
2941 if (comp > 0)
return false;
2942 return (this_len < other_len);
2946 int delta =
int(
value_.map_->size() - other.value_.map_->size());
2949 return (*
value_.map_) < (*other.value_.map_);
2968 int temp = other.type_;
2975 return value_.int_ == other.value_.int_;
2977 return value_.uint_ == other.value_.uint_;
2979 return value_.real_ == other.value_.real_;
2981 return value_.bool_ == other.value_.bool_;
2984 if ((
value_.string_ == 0) || (other.value_.string_ == 0)) {
2985 return (
value_.string_ == other.value_.string_);
2989 char const* this_str;
2990 char const* other_str;
2993 if (this_len != other_len)
return false;
2994 int comp = memcmp(this_str, other_str, this_len);
2999 return value_.map_->size() == other.value_.map_->size() &&
3000 (*
value_.map_) == (*other.value_.map_);
3009 const char* Value::asCString()
const {
3011 "in Json::Value::asCString(): requires stringValue");
3012 if (
value_.string_ == 0)
return 0;
3014 char const* this_str;
3019 bool Value::getString(
char const**
str,
char const** cend)
const {
3021 if (
value_.string_ == 0)
return false;
3034 if (
value_.string_ == 0)
return "";
3036 char const* this_str;
3041 return value_.bool_ ?
"true" :
"false";
3053 #ifdef JSON_USE_CPPTL
3054 CppTL::ConstString Value::asConstString()
const {
3059 return CppTL::ConstString(
str,
len);
3073 "double out of Int range");
3078 return value_.bool_ ? 1 : 0;
3095 "double out of UInt range");
3100 return value_.bool_ ? 1 : 0;
3107 #if defined(JSON_HAS_INT64)
3118 "double out of Int64 range");
3123 return value_.bool_ ? 1 : 0;
3139 "double out of UInt64 range");
3144 return value_.bool_ ? 1 : 0;
3150 #endif // if defined(JSON_HAS_INT64)
3153 #if defined(JSON_NO_INT64)
3161 #if defined(JSON_NO_INT64)
3168 double Value::asDouble()
const {
3171 return static_cast<double>(
value_.int_);
3173 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3174 return static_cast<double>(
value_.uint_);
3175 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3176 return integerToDouble(
value_.uint_);
3177 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3183 return value_.bool_ ? 1.0 : 0.0;
3190 float Value::asFloat()
const {
3193 return static_cast<float>(
value_.int_);
3195 #if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3196 return static_cast<float>(
value_.uint_);
3197 #else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3198 return integerToDouble(
value_.uint_);
3199 #endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
3201 return static_cast<float>(
value_.real_);
3205 return value_.bool_ ? 1.0f : 0.0f;
3212 bool Value::asBool()
const {
3231 bool Value::isConvertibleTo(
ValueType other)
const {
3234 return (isNumeric() && asDouble() == 0.0) ||
3275 if (!
value_.map_->empty()) {
3276 ObjectValues::const_iterator itLast =
value_.map_->end();
3278 return (*itLast).first.index() + 1;
3289 if (isNull() || isArray() || isObject())
3290 return size() == 0
u;
3297 void Value::clear() {
3300 "in Json::Value::clear(): requires complex value");
3315 "in Json::Value::resize(): requires arrayValue");
3321 else if (newSize > oldSize)
3322 (*this)[newSize - 1];
3327 assert(
size() == newSize);
3334 "in Json::Value::operator[](ArrayIndex): requires arrayValue");
3339 if (
it !=
value_.map_->end() && (*it).first ==
key)
3340 return (*it).second;
3344 return (*it).second;
3350 "in Json::Value::operator[](int index): index cannot be negative");
3357 "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
3361 ObjectValues::const_iterator
it =
value_.map_->find(
key);
3364 return (*it).second;
3367 const Value& Value::operator[](
int index)
const {
3370 "in Json::Value::operator[](int index) const: index cannot be negative");
3374 void Value::initBasic(
ValueType vtype,
bool allocated) {
3376 allocated_ = allocated;
3385 Value& Value::resolveReference(
const char*
key) {
3388 "in Json::Value::resolveReference(): requires objectValue");
3392 key,
static_cast<unsigned>(strlen(
key)), CZString::noDuplication);
3394 if (
it !=
value_.map_->end() && (*it).first == actualKey)
3395 return (*it).second;
3404 Value& Value::resolveReference(
char const*
key,
char const* cend)
3408 "in Json::Value::resolveReference(key, end): requires objectValue");
3412 key,
static_cast<unsigned>(cend-
key), CZString::duplicateOnCopy);
3414 if (
it !=
value_.map_->end() && (*it).first == actualKey)
3415 return (*it).second;
3425 return value == &nullRef ? defaultValue : *
value;
3434 "in Json::Value::find(key, end, found): requires objectValue or nullValue");
3436 CZString actualKey(
key,
static_cast<unsigned>(cend-
key), CZString::noDuplication);
3437 ObjectValues::const_iterator
it =
value_.map_->find(actualKey);
3438 if (
it ==
value_.map_->end())
return NULL;
3439 return &(*it).second;
3441 const Value& Value::operator[](
const char*
key)
const
3444 if (!
found)
return nullRef;
3450 if (!
found)
return nullRef;
3454 Value& Value::operator[](
const char*
key) {
3455 return resolveReference(
key,
key + strlen(
key));
3459 return resolveReference(
key.data(),
key.data() +
key.length());
3462 Value& Value::operator[](
const StaticString&
key) {
3463 return resolveReference(
key.c_str());
3466 #ifdef JSON_USE_CPPTL
3467 Value& Value::operator[](
const CppTL::ConstString&
key) {
3468 return resolveReference(
key.c_str(),
key.end_c_str());
3470 Value const& Value::operator[](CppTL::ConstString
const&
key)
const
3473 if (!
found)
return nullRef;
3491 return get(
key.data(),
key.data() +
key.length(), defaultValue);
3495 bool Value::removeMember(
const char*
key,
const char* cend,
Value* removed)
3500 CZString actualKey(
key,
static_cast<unsigned>(cend-
key), CZString::noDuplication);
3504 *removed =
it->second;
3508 bool Value::removeMember(
const char*
key,
Value* removed)
3510 return removeMember(
key,
key + strlen(
key), removed);
3514 return removeMember(
key.data(),
key.data() +
key.length(), removed);
3516 Value Value::removeMember(
const char*
key)
3519 "in Json::Value::removeMember(): requires objectValue");
3524 removeMember(
key,
key + strlen(
key), &removed);
3529 return removeMember(
key.c_str());
3541 *removed =
it->second;
3546 (*
value_.map_)[keey] = (*
this)[
i + 1];
3549 CZString keyLast(oldSize - 1);
3551 value_.map_->erase(itLast);
3555 #ifdef JSON_USE_CPPTL
3557 const Value& defaultValue)
const {
3558 return get(
key.c_str(),
key.end_c_str(), defaultValue);
3562 bool Value::isMember(
char const*
key,
char const* cend)
const
3565 return NULL !=
value;
3567 bool Value::isMember(
char const*
key)
const
3569 return isMember(
key,
key + strlen(
key));
3573 return isMember(
key.data(),
key.data() +
key.length());
3576 #ifdef JSON_USE_CPPTL
3577 bool Value::isMember(
const CppTL::ConstString&
key)
const {
3578 return isMember(
key.c_str(),
key.end_c_str());
3582 Value::Members Value::getMemberNames()
const {
3585 "in Json::Value::getMemberNames(), value must be objectValue");
3587 return Value::Members();
3589 members.reserve(
value_.map_->size());
3590 ObjectValues::const_iterator
it =
value_.map_->begin();
3591 ObjectValues::const_iterator itEnd =
value_.map_->end();
3592 for (;
it != itEnd; ++
it) {
3594 (*it).first.length()));
3625 double integral_part;
3626 return modf(
d, &integral_part) == 0.0;
3633 bool Value::isInt()
const {
3640 return value_.real_ >= minInt &&
value_.real_ <= maxInt &&
3648 bool Value::isUInt()
const {
3653 return value_.uint_ <= maxUInt;
3663 bool Value::isInt64()
const {
3664 #if defined(JSON_HAS_INT64)
3674 return value_.real_ >= double(minInt64) &&
3679 #endif // JSON_HAS_INT64
3683 bool Value::isUInt64()
const {
3684 #if defined(JSON_HAS_INT64)
3694 return value_.real_ >= 0 &&
value_.real_ < maxUInt64AsDouble &&
3699 #endif // JSON_HAS_INT64
3703 bool Value::isIntegral()
const {
3704 #if defined(JSON_HAS_INT64)
3705 return isInt64() || isUInt64();
3707 return isInt() || isUInt();
3711 bool Value::isDouble()
const {
return type_ ==
realValue || isIntegral(); }
3713 bool Value::isNumeric()
const {
return isIntegral() || isDouble(); }
3724 if ((
len > 0) && (comment[
len-1] ==
'\n')) {
3728 comments_[placement].setComment(comment,
len);
3732 setComment(comment, strlen(comment), placement);
3736 setComment(comment.c_str(), comment.length(), placement);
3740 return comments_ != 0 && comments_[placement].comment_ != 0;
3744 if (hasComment(placement))
3745 return comments_[placement].comment_;
3751 void Value::setOffsetLimit(
size_t limit) { limit_ = limit; }
3753 size_t Value::getOffsetStart()
const {
return start_; }
3755 size_t Value::getOffsetLimit()
const {
return limit_; }
3759 return writer.write(*
this);
3767 return const_iterator(
value_.map_->begin());
3772 return const_iterator();
3780 return const_iterator(
value_.map_->end());
3785 return const_iterator();
3817 PathArgument::PathArgument() :
key_(),
index_(), kind_(kindNone) {}
3822 PathArgument::PathArgument(
const char*
key)
3832 const PathArgument&
a1,
3833 const PathArgument&
a2,
3834 const PathArgument& a3,
3835 const PathArgument& a4,
3836 const PathArgument& a5) {
3847 const char* current =
path.c_str();
3848 const char*
end = current +
path.length();
3849 InArgs::const_iterator itInArg =
in.begin();
3850 while (current !=
end) {
3851 if (*current ==
'[') {
3853 if (*current ==
'%')
3854 addPathInArg(
path,
in, itInArg, PathArgument::kindIndex);
3857 for (; current !=
end && *current >=
'0' && *current <=
'9'; ++current)
3861 if (current ==
end || *current++ !=
']')
3862 invalidPath(
path,
int(current -
path.c_str()));
3863 }
else if (*current ==
'%') {
3864 addPathInArg(
path,
in, itInArg, PathArgument::kindKey);
3866 }
else if (*current ==
'.') {
3869 const char* beginName = current;
3870 while (current !=
end && !strchr(
"[.", *current))
3879 InArgs::const_iterator& itInArg,
3880 PathArgument::Kind kind) {
3881 if (itInArg ==
in.end()) {
3883 }
else if ((*itInArg)->kind_ != kind) {
3886 args_.push_back(**itInArg);
3890 void Path::invalidPath(
const std::string& ,
int ) {
3897 const PathArgument&
arg = *
it;
3898 if (
arg.kind_ == PathArgument::kindIndex) {
3899 if (!node->isArray() || !node->isValidIndex(
arg.index_)) {
3902 node = &((*node)[
arg.index_]);
3903 }
else if (
arg.kind_ == PathArgument::kindKey) {
3904 if (!node->isObject()) {
3907 node = &((*node)[
arg.key_]);
3908 if (node == &Value::nullRef) {
3920 const PathArgument&
arg = *
it;
3921 if (
arg.kind_ == PathArgument::kindIndex) {
3922 if (!node->isArray() || !node->isValidIndex(
arg.index_))
3923 return defaultValue;
3924 node = &((*node)[
arg.index_]);
3925 }
else if (
arg.kind_ == PathArgument::kindKey) {
3926 if (!node->isObject())
3927 return defaultValue;
3928 node = &((*node)[
arg.key_]);
3929 if (node == &Value::nullRef)
3930 return defaultValue;
3939 const PathArgument&
arg = *
it;
3940 if (
arg.kind_ == PathArgument::kindIndex) {
3941 if (!node->isArray()) {
3944 node = &((*node)[
arg.index_]);
3945 }
else if (
arg.kind_ == PathArgument::kindKey) {
3946 if (!node->isObject()) {
3949 node = &((*node)[
arg.key_]);
3975 #if !defined(JSON_IS_AMALGAMATION)
3976 #include <json/writer.h>
3977 #include "json_tool.h"
3978 #endif // if !defined(JSON_IS_AMALGAMATION)
3988 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
3990 #define isfinite _finite
3991 #elif defined(__sun) && defined(__SVR4) //Solaris
3992 #if !defined(isfinite)
3994 #define isfinite finite
3997 #if !defined(isfinite)
3999 #define isfinite finite
4001 #elif defined(__hpux)
4002 #if !defined(isfinite)
4003 #if defined(__ia64) && !defined(finite)
4004 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \
4005 _Isfinitef(x) : _IsFinite(x)))
4008 #define isfinite finite
4013 #if !(defined(__QNXNTO__)) // QNX already defines isfinite
4014 #define isfinite std::isfinite
4018 #if defined(_MSC_VER)
4019 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
4020 #define snprintf sprintf_s
4021 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
4022 #define snprintf std::snprintf
4024 #define snprintf _snprintf
4026 #elif defined(__ANDROID__) || defined(__QNXNTO__)
4027 #define snprintf snprintf
4028 #elif __cplusplus >= 201103L
4029 #define snprintf std::snprintf
4032 #if defined(__BORLANDC__)
4034 #define isfinite _finite
4035 #define snprintf _snprintf
4038 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
4040 #pragma warning(disable : 4996)
4045 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
4075 }
else if (
value < 0) {
4081 assert(current >=
buffer);
4089 assert(current >=
buffer);
4093 #if defined(JSON_HAS_INT64)
4103 #endif // # if defined(JSON_HAS_INT64)
4111 char formatString[6];
4112 sprintf(formatString,
"%%.%dg",
precision);
4122 len = snprintf(
buffer,
sizeof(
buffer), useSpecialFloats ?
"NaN" :
"null");
4123 }
else if (
value < 0) {
4124 len = snprintf(
buffer,
sizeof(
buffer), useSpecialFloats ?
"-Infinity" :
"-1e+9999");
4126 len = snprintf(
buffer,
sizeof(
buffer), useSpecialFloats ?
"Infinity" :
"1e+9999");
4143 if (strpbrk(
value,
"\"\\\b\f\n\r\t") == NULL &&
4149 std::string::size_type
maxsize =
4150 strlen(
value) * 2 + 3;
4154 for (
const char* c =
value; *
c != 0; ++
c) {
4187 std::ostringstream oss;
4188 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
4189 << std::setw(4) <<
static_cast<int>(*c);
4202 static char const*
strnpbrk(
char const* s,
char const* accept,
size_t n) {
4203 assert((s || !
n) && accept);
4205 char const*
const end = s +
n;
4208 for (
char const*
a = accept; *
a; ++
a) {
4226 std::string::size_type
maxsize =
4232 for (
const char* c =
value; c !=
end; ++c) {
4265 std::ostringstream oss;
4266 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
4267 << std::setw(4) <<
static_cast<int>(*c);
4287 : yamlCompatiblityEnabled_(
false), dropNullPlaceholders_(
false),
4288 omitEndingLineFeed_(
false) {}
4290 void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ =
true; }
4292 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ =
true; }
4294 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ =
true; }
4299 if (!omitEndingLineFeed_)
4304 void FastWriter::writeValue(
const Value&
value) {
4305 switch (
value.type()) {
4307 if (!dropNullPlaceholders_)
4308 document_ +=
"null";
4342 Value::Members members(
value.getMemberNames());
4347 if (
it != members.begin())
4350 document_ += yamlCompatiblityEnabled_ ?
": " :
":";
4361 StyledWriter::StyledWriter()
4362 : rightMargin_(74), indentSize_(3), addChildValues_() {}
4366 addChildValues_ =
false;
4368 writeCommentBeforeValue(
root);
4370 writeCommentAfterValueOnSameLine(
root);
4375 void StyledWriter::writeValue(
const Value&
value) {
4376 switch (
value.type()) {
4403 writeArrayValue(
value);
4406 Value::Members members(
value.getMemberNames());
4407 if (members.empty())
4410 writeWithIndent(
"{");
4416 writeCommentBeforeValue(childValue);
4419 writeValue(childValue);
4420 if (++
it == members.end()) {
4421 writeCommentAfterValueOnSameLine(childValue);
4425 writeCommentAfterValueOnSameLine(childValue);
4428 writeWithIndent(
"}");
4434 void StyledWriter::writeArrayValue(
const Value&
value) {
4439 bool isArrayMultiLine = isMultineArray(
value);
4440 if (isArrayMultiLine) {
4441 writeWithIndent(
"[");
4443 bool hasChildValue = !childValues_.empty();
4447 writeCommentBeforeValue(childValue);
4449 writeWithIndent(childValues_[
index]);
4452 writeValue(childValue);
4455 writeCommentAfterValueOnSameLine(childValue);
4459 writeCommentAfterValueOnSameLine(childValue);
4462 writeWithIndent(
"]");
4465 assert(childValues_.size() ==
size);
4470 document_ += childValues_[
index];
4477 bool StyledWriter::isMultineArray(
const Value&
value) {
4479 bool isMultiLine =
size * 3 >= rightMargin_;
4480 childValues_.clear();
4483 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4484 childValue.size() > 0);
4488 childValues_.reserve(
size);
4489 addChildValues_ =
true;
4490 int lineLength = 4 + (
size - 1) * 2;
4498 addChildValues_ =
false;
4499 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4505 if (addChildValues_)
4506 childValues_.push_back(
value);
4511 void StyledWriter::writeIndent() {
4512 if (!document_.empty()) {
4513 char last = document_[document_.length() - 1];
4519 document_ += indentString_;
4529 void StyledWriter::unindent() {
4530 assert(
int(indentString_.size()) >= indentSize_);
4531 indentString_.resize(indentString_.size() - indentSize_);
4534 void StyledWriter::writeCommentBeforeValue(
const Value&
root) {
4541 std::string::const_iterator
iter = comment.begin();
4542 while (
iter != comment.end()) {
4544 if (*
iter ==
'\n' &&
4545 (
iter != comment.end() && *(
iter + 1) ==
'/'))
4554 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value&
root) {
4565 bool StyledWriter::hasCommentForValue(
const Value&
value) {
4574 StyledStreamWriter::StyledStreamWriter(
std::string indentation)
4575 : document_(NULL), rightMargin_(74), indentation_(indentation),
4576 addChildValues_() {}
4580 addChildValues_ =
false;
4583 writeCommentBeforeValue(
root);
4584 if (!indented_) writeIndent();
4587 writeCommentAfterValueOnSameLine(
root);
4592 void StyledStreamWriter::writeValue(
const Value&
value) {
4593 switch (
value.type()) {
4620 writeArrayValue(
value);
4623 Value::Members members(
value.getMemberNames());
4624 if (members.empty())
4627 writeWithIndent(
"{");
4633 writeCommentBeforeValue(childValue);
4635 *document_ <<
" : ";
4636 writeValue(childValue);
4637 if (++
it == members.end()) {
4638 writeCommentAfterValueOnSameLine(childValue);
4642 writeCommentAfterValueOnSameLine(childValue);
4645 writeWithIndent(
"}");
4651 void StyledStreamWriter::writeArrayValue(
const Value&
value) {
4656 bool isArrayMultiLine = isMultineArray(
value);
4657 if (isArrayMultiLine) {
4658 writeWithIndent(
"[");
4660 bool hasChildValue = !childValues_.empty();
4664 writeCommentBeforeValue(childValue);
4666 writeWithIndent(childValues_[
index]);
4668 if (!indented_) writeIndent();
4670 writeValue(childValue);
4674 writeCommentAfterValueOnSameLine(childValue);
4678 writeCommentAfterValueOnSameLine(childValue);
4681 writeWithIndent(
"]");
4684 assert(childValues_.size() ==
size);
4689 *document_ << childValues_[
index];
4696 bool StyledStreamWriter::isMultineArray(
const Value&
value) {
4698 bool isMultiLine =
size * 3 >= rightMargin_;
4699 childValues_.clear();
4702 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4703 childValue.size() > 0);
4707 childValues_.reserve(
size);
4708 addChildValues_ =
true;
4709 int lineLength = 4 + (
size - 1) * 2;
4717 addChildValues_ =
false;
4718 isMultiLine = isMultiLine || lineLength >= rightMargin_;
4724 if (addChildValues_)
4725 childValues_.push_back(
value);
4727 *document_ <<
value;
4730 void StyledStreamWriter::writeIndent() {
4735 *document_ <<
'\n' << indentString_;
4739 if (!indented_) writeIndent();
4740 *document_ <<
value;
4746 void StyledStreamWriter::unindent() {
4747 assert(indentString_.size() >= indentation_.size());
4748 indentString_.resize(indentString_.size() - indentation_.size());
4751 void StyledStreamWriter::writeCommentBeforeValue(
const Value&
root) {
4755 if (!indented_) writeIndent();
4757 std::string::const_iterator
iter = comment.begin();
4758 while (
iter != comment.end()) {
4759 *document_ << *
iter;
4760 if (*
iter ==
'\n' &&
4761 (
iter != comment.end() && *(
iter + 1) ==
'/'))
4763 *document_ << indentString_;
4769 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value&
root) {
4780 bool StyledStreamWriter::hasCommentForValue(
const Value&
value) {
4790 struct CommentStyle {
4799 struct BuiltStyledStreamWriter :
public StreamWriter
4801 BuiltStyledStreamWriter(
4807 bool useSpecialFloats,
4819 void writeCommentBeforeValue(
Value const&
root);
4820 void writeCommentAfterValueOnSameLine(
Value const&
root);
4821 static bool hasCommentForValue(
const Value&
value);
4833 bool addChildValues_ : 1;
4835 bool useSpecialFloats_ : 1;
4836 unsigned int precision_;
4838 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
4844 bool useSpecialFloats,
4847 , indentation_(indentation)
4849 , colonSymbol_(colonSymbol)
4850 , nullSymbol_(nullSymbol)
4851 , endingLineFeedSymbol_(endingLineFeedSymbol)
4852 , addChildValues_(
false)
4854 , useSpecialFloats_(useSpecialFloats)
4874 switch (
value.type()) {
4905 if (members.empty())
4918 if (++
it == members.end()) {
4985 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
4986 childValue.size() > 0);
4992 int lineLength = 4 + (
size - 1) * 2;
5001 isMultiLine = isMultiLine || lineLength >=
rightMargin_;
5045 std::string::const_iterator
iter = comment.begin();
5046 while (
iter != comment.end()) {
5048 if (*
iter ==
'\n' &&
5049 (
iter != comment.end() && *(
iter + 1) ==
'/'))
5089 setDefaults(&settings_);
5095 std::string indentation = settings_[
"indentation"].asString();
5096 std::string cs_str = settings_[
"commentStyle"].asString();
5097 bool eyc = settings_[
"enableYAMLCompatibility"].asBool();
5098 bool dnp = settings_[
"dropNullPlaceholders"].asBool();
5099 bool usf = settings_[
"useSpecialFloats"].asBool();
5100 unsigned int pre = settings_[
"precision"].asUInt();
5102 if (cs_str ==
"All") {
5104 }
else if (cs_str ==
"None") {
5112 }
else if (indentation.empty()) {
5119 if (pre > 17) pre = 17;
5121 return new BuiltStyledStreamWriter(
5123 colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
5127 valid_keys->clear();
5128 valid_keys->insert(
"indentation");
5129 valid_keys->insert(
"commentStyle");
5130 valid_keys->insert(
"enableYAMLCompatibility");
5131 valid_keys->insert(
"dropNullPlaceholders");
5132 valid_keys->insert(
"useSpecialFloats");
5133 valid_keys->insert(
"precision");
5140 std::set<std::string> valid_keys;
5143 size_t n =
keys.size();
5144 for (
size_t i = 0;
i <
n; ++
i) {
5146 if (valid_keys.find(
key) == valid_keys.end()) {
5147 inv[
key] = settings_[
key];
5150 return 0
u == inv.
size();
5154 return settings_[
key];
5160 (*settings)[
"commentStyle"] =
"All";
5161 (*settings)[
"indentation"] =
"\t";
5162 (*settings)[
"enableYAMLCompatibility"] =
false;
5163 (*settings)[
"dropNullPlaceholders"] =
false;
5164 (*settings)[
"useSpecialFloats"] =
false;
5165 (*settings)[
"precision"] = 17;
5170 std::ostringstream sout;