6 #if !defined(JSON_IS_AMALGAMATION)
9 #endif // if !defined(JSON_IS_AMALGAMATION)
19 #if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
21 #define isfinite _finite
22 #elif defined(__sun) && defined(__SVR4) //Solaris
23 #if !defined(isfinite)
25 #define isfinite finite
28 #if !defined(isfinite)
30 #define isfinite finite
33 #if !defined(isfinite)
34 #if defined(__ia64) && !defined(finite)
35 #define isfinite(x) ((sizeof(x) == sizeof(float) ? \
36 _Isfinitef(x) : _IsFinite(x)))
39 #define isfinite finite
44 #if !(defined(__QNXNTO__)) // QNX already defines isfinite
45 #define isfinite std::isfinite
50 #if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
51 #define snprintf sprintf_s
52 #elif _MSC_VER >= 1900 // VC++ 14.0 and above
53 #define snprintf std::snprintf
55 #define snprintf _snprintf
57 #elif defined(__ANDROID__) || defined(__QNXNTO__)
58 #define snprintf snprintf
59 #elif __cplusplus >= 201103L
60 #if !defined(__MINGW32__) && !defined(__CYGWIN__)
61 #define snprintf std::snprintf
65 #if defined(__BORLANDC__)
67 #define isfinite _finite
68 #define snprintf _snprintf
71 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
73 #pragma warning(disable : 4996)
78 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
93 char const* end = str + len;
104 char* current = buffer +
sizeof(buffer);
108 }
else if (value < 0) {
114 assert(current >= buffer);
120 char* current = buffer +
sizeof(buffer);
122 assert(current >= buffer);
126 #if defined(JSON_HAS_INT64)
136 #endif // # if defined(JSON_HAS_INT64)
145 char formatString[6];
146 sprintf(formatString,
"%%.%dg", precision);
152 len =
snprintf(buffer,
sizeof(buffer), formatString, value);
155 if (value != value) {
156 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"NaN" :
"null");
157 }
else if (value < 0) {
158 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"-Infinity" :
"-1e+9999");
160 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"Infinity" :
"1e+9999");
178 if (strpbrk(value,
"\"\\\b\f\n\r\t") == NULL &&
184 JSONCPP_STRING::size_type maxsize =
185 strlen(value) * 2 + 3;
187 result.reserve(maxsize);
189 for (
const char* c = value; *c != 0; ++c) {
223 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
224 << std::setw(4) << static_cast<int>(*c);
237 static char const*
strnpbrk(
char const* s,
char const* accept,
size_t n) {
238 assert((s || !n) && accept);
240 char const*
const end = s + n;
241 for (
char const* cur = s; cur < end; ++cur) {
243 for (
char const* a = accept; *a; ++a) {
255 if (
strnpbrk(value,
"\"\\\b\f\n\r\t", length) == NULL &&
261 JSONCPP_STRING::size_type maxsize =
264 result.reserve(maxsize);
266 char const* end = value + length;
267 for (
const char* c = value; c != end; ++c) {
301 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
302 << std::setw(4) << static_cast<int>(*c);
322 : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
323 omitEndingLineFeed_(false) {}
334 if (!omitEndingLineFeed_)
339 void FastWriter::writeValue(
const Value& value) {
340 switch (value.
type()) {
342 if (!dropNullPlaceholders_)
369 for (
ArrayIndex index = 0; index < size; ++index) {
372 writeValue(value[index]);
379 for (Value::Members::iterator it = members.begin(); it != members.end();
382 if (it != members.begin())
385 document_ += yamlCompatiblityEnabled_ ?
": " :
":";
386 writeValue(value[name]);
397 : rightMargin_(74), indentSize_(3), addChildValues_() {}
401 addChildValues_ =
false;
403 writeCommentBeforeValue(root);
405 writeCommentAfterValueOnSameLine(root);
410 void StyledWriter::writeValue(
const Value& value) {
411 switch (value.
type()) {
438 writeArrayValue(value);
445 writeWithIndent(
"{");
447 Value::Members::iterator it = members.begin();
450 const Value& childValue = value[name];
451 writeCommentBeforeValue(childValue);
454 writeValue(childValue);
455 if (++it == members.end()) {
456 writeCommentAfterValueOnSameLine(childValue);
460 writeCommentAfterValueOnSameLine(childValue);
463 writeWithIndent(
"}");
469 void StyledWriter::writeArrayValue(
const Value& value) {
470 unsigned size = value.size();
474 bool isArrayMultiLine = isMultineArray(value);
475 if (isArrayMultiLine) {
476 writeWithIndent(
"[");
478 bool hasChildValue = !childValues_.empty();
481 const Value& childValue = value[index];
482 writeCommentBeforeValue(childValue);
484 writeWithIndent(childValues_[index]);
487 writeValue(childValue);
489 if (++index == size) {
490 writeCommentAfterValueOnSameLine(childValue);
494 writeCommentAfterValueOnSameLine(childValue);
497 writeWithIndent(
"]");
500 assert(childValues_.size() == size);
502 for (
unsigned index = 0; index < size; ++index) {
505 document_ += childValues_[index];
512 bool StyledWriter::isMultineArray(
const Value& value) {
514 bool isMultiLine = size * 3 >= rightMargin_;
515 childValues_.clear();
516 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
517 const Value& childValue = value[index];
518 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
519 childValue.size() > 0);
523 childValues_.reserve(size);
524 addChildValues_ =
true;
526 for (
ArrayIndex index = 0; index < size; ++index) {
527 if (hasCommentForValue(value[index])) {
530 writeValue(value[index]);
531 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
533 addChildValues_ =
false;
534 isMultiLine = isMultiLine || lineLength >= rightMargin_;
541 childValues_.push_back(value);
546 void StyledWriter::writeIndent() {
547 if (!document_.empty()) {
548 char last = document_[document_.length() - 1];
554 document_ += indentString_;
562 void StyledWriter::indent() { indentString_ +=
JSONCPP_STRING(indentSize_,
' '); }
564 void StyledWriter::unindent() {
565 assert(indentString_.size() >= indentSize_);
566 indentString_.resize(indentString_.size() - indentSize_);
569 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
576 JSONCPP_STRING::const_iterator iter = comment.begin();
577 while (iter != comment.end()) {
580 (iter != comment.end() && *(iter + 1) ==
'/'))
589 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
600 bool StyledWriter::hasCommentForValue(
const Value& value) {
610 : document_(NULL), rightMargin_(74), indentation_(indentation),
615 addChildValues_ =
false;
618 writeCommentBeforeValue(root);
619 if (!indented_) writeIndent();
622 writeCommentAfterValueOnSameLine(root);
627 void StyledStreamWriter::writeValue(
const Value& value) {
628 switch (value.
type()) {
655 writeArrayValue(value);
662 writeWithIndent(
"{");
664 Value::Members::iterator it = members.begin();
667 const Value& childValue = value[name];
668 writeCommentBeforeValue(childValue);
671 writeValue(childValue);
672 if (++it == members.end()) {
673 writeCommentAfterValueOnSameLine(childValue);
677 writeCommentAfterValueOnSameLine(childValue);
680 writeWithIndent(
"}");
686 void StyledStreamWriter::writeArrayValue(
const Value& value) {
687 unsigned size = value.size();
691 bool isArrayMultiLine = isMultineArray(value);
692 if (isArrayMultiLine) {
693 writeWithIndent(
"[");
695 bool hasChildValue = !childValues_.empty();
698 const Value& childValue = value[index];
699 writeCommentBeforeValue(childValue);
701 writeWithIndent(childValues_[index]);
703 if (!indented_) writeIndent();
705 writeValue(childValue);
708 if (++index == size) {
709 writeCommentAfterValueOnSameLine(childValue);
713 writeCommentAfterValueOnSameLine(childValue);
716 writeWithIndent(
"]");
719 assert(childValues_.size() == size);
721 for (
unsigned index = 0; index < size; ++index) {
724 *document_ << childValues_[index];
731 bool StyledStreamWriter::isMultineArray(
const Value& value) {
733 bool isMultiLine = size * 3 >= rightMargin_;
734 childValues_.clear();
735 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
736 const Value& childValue = value[index];
737 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
738 childValue.size() > 0);
742 childValues_.reserve(size);
743 addChildValues_ =
true;
745 for (
ArrayIndex index = 0; index < size; ++index) {
746 if (hasCommentForValue(value[index])) {
749 writeValue(value[index]);
750 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
752 addChildValues_ =
false;
753 isMultiLine = isMultiLine || lineLength >= rightMargin_;
760 childValues_.push_back(value);
765 void StyledStreamWriter::writeIndent() {
770 *document_ <<
'\n' << indentString_;
773 void StyledStreamWriter::writeWithIndent(
const JSONCPP_STRING& value) {
774 if (!indented_) writeIndent();
779 void StyledStreamWriter::indent() { indentString_ += indentation_; }
781 void StyledStreamWriter::unindent() {
782 assert(indentString_.size() >= indentation_.size());
783 indentString_.resize(indentString_.size() - indentation_.size());
786 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
790 if (!indented_) writeIndent();
792 JSONCPP_STRING::const_iterator iter = comment.begin();
793 while (iter != comment.end()) {
796 (iter != comment.end() && *(iter + 1) ==
'/'))
798 *document_ << indentString_;
804 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
815 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
825 struct CommentStyle {
834 struct BuiltStyledStreamWriter :
public StreamWriter
836 BuiltStyledStreamWriter(
838 CommentStyle::Enum cs,
842 bool useSpecialFloats,
843 unsigned int precision);
846 void writeValue(Value
const& value);
847 void writeArrayValue(Value
const& value);
848 bool isMultineArray(Value
const& value);
854 void writeCommentBeforeValue(Value
const& root);
855 void writeCommentAfterValueOnSameLine(Value
const& root);
856 static bool hasCommentForValue(
const Value& value);
858 typedef std::vector<JSONCPP_STRING> ChildValues;
860 ChildValues childValues_;
862 unsigned int rightMargin_;
864 CommentStyle::Enum cs_;
868 bool addChildValues_ : 1;
870 bool useSpecialFloats_ : 1;
871 unsigned int precision_;
873 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
875 CommentStyle::Enum cs,
879 bool useSpecialFloats,
880 unsigned int precision)
882 , indentation_(indentation)
884 , colonSymbol_(colonSymbol)
885 , nullSymbol_(nullSymbol)
886 , endingLineFeedSymbol_(endingLineFeedSymbol)
887 , addChildValues_(false)
889 , useSpecialFloats_(useSpecialFloats)
890 , precision_(precision)
893 int BuiltStyledStreamWriter::write(Value
const& root,
JSONCPP_OSTREAM* sout)
896 addChildValues_ =
false;
899 writeCommentBeforeValue(root);
900 if (!indented_) writeIndent();
903 writeCommentAfterValueOnSameLine(root);
904 *sout_ << endingLineFeedSymbol_;
908 void BuiltStyledStreamWriter::writeValue(Value
const& value) {
909 switch (value.type()) {
911 pushValue(nullSymbol_);
920 pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_));
927 bool ok = value.getString(&str, &end);
936 writeArrayValue(value);
943 writeWithIndent(
"{");
945 Value::Members::iterator it = members.begin();
948 Value
const& childValue = value[name];
949 writeCommentBeforeValue(childValue);
951 *sout_ << colonSymbol_;
952 writeValue(childValue);
953 if (++it == members.end()) {
954 writeCommentAfterValueOnSameLine(childValue);
958 writeCommentAfterValueOnSameLine(childValue);
961 writeWithIndent(
"}");
967 void BuiltStyledStreamWriter::writeArrayValue(Value
const& value) {
968 unsigned size = value.size();
972 bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
974 writeWithIndent(
"[");
976 bool hasChildValue = !childValues_.empty();
979 Value
const& childValue = value[index];
980 writeCommentBeforeValue(childValue);
982 writeWithIndent(childValues_[index]);
984 if (!indented_) writeIndent();
986 writeValue(childValue);
989 if (++index == size) {
990 writeCommentAfterValueOnSameLine(childValue);
994 writeCommentAfterValueOnSameLine(childValue);
997 writeWithIndent(
"]");
1000 assert(childValues_.size() == size);
1002 if (!indentation_.empty()) *sout_ <<
" ";
1003 for (
unsigned index = 0; index < size; ++index) {
1006 *sout_ << childValues_[index];
1008 if (!indentation_.empty()) *sout_ <<
" ";
1014 bool BuiltStyledStreamWriter::isMultineArray(Value
const& value) {
1016 bool isMultiLine = size * 3 >= rightMargin_;
1017 childValues_.clear();
1018 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
1019 Value
const& childValue = value[index];
1020 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
1021 childValue.size() > 0);
1025 childValues_.reserve(size);
1026 addChildValues_ =
true;
1028 for (
ArrayIndex index = 0; index < size; ++index) {
1029 if (hasCommentForValue(value[index])) {
1032 writeValue(value[index]);
1033 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
1035 addChildValues_ =
false;
1036 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1041 void BuiltStyledStreamWriter::pushValue(
JSONCPP_STRING const& value) {
1042 if (addChildValues_)
1043 childValues_.push_back(value);
1048 void BuiltStyledStreamWriter::writeIndent() {
1054 if (!indentation_.empty()) {
1056 *sout_ <<
'\n' << indentString_;
1060 void BuiltStyledStreamWriter::writeWithIndent(
JSONCPP_STRING const& value) {
1061 if (!indented_) writeIndent();
1066 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1068 void BuiltStyledStreamWriter::unindent() {
1069 assert(indentString_.size() >= indentation_.size());
1070 indentString_.resize(indentString_.size() - indentation_.size());
1073 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value
const& root) {
1074 if (cs_ == CommentStyle::None)
return;
1078 if (!indented_) writeIndent();
1080 JSONCPP_STRING::const_iterator iter = comment.begin();
1081 while (iter != comment.end()) {
1083 if (*iter ==
'\n' &&
1084 (iter != comment.end() && *(iter + 1) ==
'/'))
1086 *sout_ << indentString_;
1092 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value
const& root) {
1093 if (cs_ == CommentStyle::None)
return;
1104 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1124 setDefaults(&settings_);
1130 JSONCPP_STRING indentation = settings_[
"indentation"].asString();
1132 bool eyc = settings_[
"enableYAMLCompatibility"].asBool();
1133 bool dnp = settings_[
"dropNullPlaceholders"].asBool();
1134 bool usf = settings_[
"useSpecialFloats"].asBool();
1135 unsigned int pre = settings_[
"precision"].asUInt();
1136 CommentStyle::Enum cs = CommentStyle::All;
1137 if (cs_str ==
"All") {
1138 cs = CommentStyle::All;
1139 }
else if (cs_str ==
"None") {
1140 cs = CommentStyle::None;
1142 throwRuntimeError(
"commentStyle must be 'All' or 'None'");
1147 }
else if (indentation.empty()) {
1154 if (pre > 17) pre = 17;
1156 return new BuiltStyledStreamWriter(
1158 colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
1162 valid_keys->clear();
1163 valid_keys->insert(
"indentation");
1164 valid_keys->insert(
"commentStyle");
1165 valid_keys->insert(
"enableYAMLCompatibility");
1166 valid_keys->insert(
"dropNullPlaceholders");
1167 valid_keys->insert(
"useSpecialFloats");
1168 valid_keys->insert(
"precision");
1173 if (!invalid) invalid = &my_invalid;
1175 std::set<JSONCPP_STRING> valid_keys;
1178 size_t n = keys.size();
1179 for (
size_t i = 0; i < n; ++i) {
1181 if (valid_keys.find(key) == valid_keys.end()) {
1182 inv[key] = settings_[key];
1185 return 0u == inv.
size();
1189 return settings_[key];
1195 (*settings)[
"commentStyle"] =
"All";
1196 (*settings)[
"indentation"] =
"\t";
1197 (*settings)[
"enableYAMLCompatibility"] =
false;
1198 (*settings)[
"dropNullPlaceholders"] =
false;
1199 (*settings)[
"useSpecialFloats"] =
false;
1200 (*settings)[
"precision"] = 17;
1207 writer->write(root, &sout);
1214 writer->write(root, &sout);