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 #define snprintf std::snprintf
63 #if defined(__BORLANDC__)
65 #define isfinite _finite
66 #define snprintf _snprintf
69 #if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
71 #pragma warning(disable : 4996)
76 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
91 char const* end = str + len;
102 char* current = buffer +
sizeof(buffer);
106 }
else if (value < 0) {
112 assert(current >= buffer);
118 char* current = buffer +
sizeof(buffer);
120 assert(current >= buffer);
124 #if defined(JSON_HAS_INT64)
134 #endif // # if defined(JSON_HAS_INT64)
136 std::string
valueToString(
double value,
bool useSpecialFloats,
unsigned int precision) {
142 char formatString[6];
143 sprintf(formatString,
"%%.%dg", precision);
149 len =
snprintf(buffer,
sizeof(buffer), formatString, value);
152 if (value != value) {
153 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"NaN" :
"null");
154 }
else if (value < 0) {
155 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"-Infinity" :
"-1e+9999");
157 len =
snprintf(buffer,
sizeof(buffer), useSpecialFloats ?
"Infinity" :
"1e+9999");
174 if (strpbrk(value,
"\"\\\b\f\n\r\t") == NULL &&
176 return std::string(
"\"") + value +
"\"";
180 std::string::size_type maxsize =
181 strlen(value) * 2 + 3;
183 result.reserve(maxsize);
185 for (
const char* c = value; *c != 0; ++c) {
218 std::ostringstream oss;
219 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
220 << std::setw(4) <<
static_cast<int>(*c);
233 static char const*
strnpbrk(
char const* s,
char const* accept,
size_t n) {
234 assert((s || !n) && accept);
236 char const*
const end = s + n;
237 for (
char const* cur = s; cur < end; ++cur) {
239 for (
char const* a = accept; *a; ++a) {
251 if (
strnpbrk(value,
"\"\\\b\f\n\r\t", length) == NULL &&
253 return std::string(
"\"") + value +
"\"";
257 std::string::size_type maxsize =
260 result.reserve(maxsize);
262 char const* end = value + length;
263 for (
const char* c = value; c != end; ++c) {
296 std::ostringstream oss;
297 oss <<
"\\u" << std::hex << std::uppercase << std::setfill(
'0')
298 << std::setw(4) <<
static_cast<int>(*c);
318 : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
319 omitEndingLineFeed_(false) {}
330 if (!omitEndingLineFeed_)
335 void FastWriter::writeValue(
const Value& value) {
336 switch (value.
type()) {
338 if (!dropNullPlaceholders_)
364 int size = value.
size();
365 for (
int index = 0; index < size; ++index) {
368 writeValue(value[index]);
375 for (Value::Members::iterator it = members.begin(); it != members.end();
377 const std::string& name = *it;
378 if (it != members.begin())
381 document_ += yamlCompatiblityEnabled_ ?
": " :
":";
382 writeValue(value[name]);
393 : rightMargin_(74), indentSize_(3), addChildValues_() {}
397 addChildValues_ =
false;
399 writeCommentBeforeValue(root);
401 writeCommentAfterValueOnSameLine(root);
406 void StyledWriter::writeValue(
const Value& value) {
407 switch (value.
type()) {
434 writeArrayValue(value);
441 writeWithIndent(
"{");
443 Value::Members::iterator it = members.begin();
445 const std::string& name = *it;
446 const Value& childValue = value[name];
447 writeCommentBeforeValue(childValue);
450 writeValue(childValue);
451 if (++it == members.end()) {
452 writeCommentAfterValueOnSameLine(childValue);
456 writeCommentAfterValueOnSameLine(childValue);
459 writeWithIndent(
"}");
465 void StyledWriter::writeArrayValue(
const Value& value) {
466 unsigned size = value.size();
470 bool isArrayMultiLine = isMultineArray(value);
471 if (isArrayMultiLine) {
472 writeWithIndent(
"[");
474 bool hasChildValue = !childValues_.empty();
477 const Value& childValue = value[index];
478 writeCommentBeforeValue(childValue);
480 writeWithIndent(childValues_[index]);
483 writeValue(childValue);
485 if (++index == size) {
486 writeCommentAfterValueOnSameLine(childValue);
490 writeCommentAfterValueOnSameLine(childValue);
493 writeWithIndent(
"]");
496 assert(childValues_.size() == size);
498 for (
unsigned index = 0; index < size; ++index) {
501 document_ += childValues_[index];
508 bool StyledWriter::isMultineArray(
const Value& value) {
509 int size = value.size();
510 bool isMultiLine = size * 3 >= rightMargin_;
511 childValues_.clear();
512 for (
int index = 0; index < size && !isMultiLine; ++index) {
513 const Value& childValue = value[index];
514 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
515 childValue.size() > 0);
519 childValues_.reserve(size);
520 addChildValues_ =
true;
521 int lineLength = 4 + (size - 1) * 2;
522 for (
int index = 0; index < size; ++index) {
523 if (hasCommentForValue(value[index])) {
526 writeValue(value[index]);
527 lineLength += int(childValues_[index].length());
529 addChildValues_ =
false;
530 isMultiLine = isMultiLine || lineLength >= rightMargin_;
535 void StyledWriter::pushValue(
const std::string& value) {
537 childValues_.push_back(value);
542 void StyledWriter::writeIndent() {
543 if (!document_.empty()) {
544 char last = document_[document_.length() - 1];
550 document_ += indentString_;
553 void StyledWriter::writeWithIndent(
const std::string& value) {
558 void StyledWriter::indent() { indentString_ += std::string(indentSize_,
' '); }
560 void StyledWriter::unindent() {
561 assert(
int(indentString_.size()) >= indentSize_);
562 indentString_.resize(indentString_.size() - indentSize_);
565 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
572 std::string::const_iterator iter = comment.begin();
573 while (iter != comment.end()) {
576 (iter != comment.end() && *(iter + 1) ==
'/'))
585 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
596 bool StyledWriter::hasCommentForValue(
const Value& value) {
606 : document_(NULL), rightMargin_(74), indentation_(indentation),
611 addChildValues_ =
false;
614 writeCommentBeforeValue(root);
615 if (!indented_) writeIndent();
618 writeCommentAfterValueOnSameLine(root);
623 void StyledStreamWriter::writeValue(
const Value& value) {
624 switch (value.
type()) {
651 writeArrayValue(value);
658 writeWithIndent(
"{");
660 Value::Members::iterator it = members.begin();
662 const std::string& name = *it;
663 const Value& childValue = value[name];
664 writeCommentBeforeValue(childValue);
667 writeValue(childValue);
668 if (++it == members.end()) {
669 writeCommentAfterValueOnSameLine(childValue);
673 writeCommentAfterValueOnSameLine(childValue);
676 writeWithIndent(
"}");
682 void StyledStreamWriter::writeArrayValue(
const Value& value) {
683 unsigned size = value.size();
687 bool isArrayMultiLine = isMultineArray(value);
688 if (isArrayMultiLine) {
689 writeWithIndent(
"[");
691 bool hasChildValue = !childValues_.empty();
694 const Value& childValue = value[index];
695 writeCommentBeforeValue(childValue);
697 writeWithIndent(childValues_[index]);
699 if (!indented_) writeIndent();
701 writeValue(childValue);
704 if (++index == size) {
705 writeCommentAfterValueOnSameLine(childValue);
709 writeCommentAfterValueOnSameLine(childValue);
712 writeWithIndent(
"]");
715 assert(childValues_.size() == size);
717 for (
unsigned index = 0; index < size; ++index) {
720 *document_ << childValues_[index];
727 bool StyledStreamWriter::isMultineArray(
const Value& value) {
728 int size = value.size();
729 bool isMultiLine = size * 3 >= rightMargin_;
730 childValues_.clear();
731 for (
int index = 0; index < size && !isMultiLine; ++index) {
732 const Value& childValue = value[index];
733 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
734 childValue.size() > 0);
738 childValues_.reserve(size);
739 addChildValues_ =
true;
740 int lineLength = 4 + (size - 1) * 2;
741 for (
int index = 0; index < size; ++index) {
742 if (hasCommentForValue(value[index])) {
745 writeValue(value[index]);
746 lineLength += int(childValues_[index].length());
748 addChildValues_ =
false;
749 isMultiLine = isMultiLine || lineLength >= rightMargin_;
754 void StyledStreamWriter::pushValue(
const std::string& value) {
756 childValues_.push_back(value);
761 void StyledStreamWriter::writeIndent() {
766 *document_ <<
'\n' << indentString_;
769 void StyledStreamWriter::writeWithIndent(
const std::string& value) {
770 if (!indented_) writeIndent();
775 void StyledStreamWriter::indent() { indentString_ += indentation_; }
777 void StyledStreamWriter::unindent() {
778 assert(indentString_.size() >= indentation_.size());
779 indentString_.resize(indentString_.size() - indentation_.size());
782 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
786 if (!indented_) writeIndent();
788 std::string::const_iterator iter = comment.begin();
789 while (iter != comment.end()) {
792 (iter != comment.end() && *(iter + 1) ==
'/'))
794 *document_ << indentString_;
800 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
811 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
821 struct CommentStyle {
830 struct BuiltStyledStreamWriter :
public StreamWriter
832 BuiltStyledStreamWriter(
833 std::string
const& indentation,
834 CommentStyle::Enum cs,
835 std::string
const& colonSymbol,
836 std::string
const& nullSymbol,
837 std::string
const& endingLineFeedSymbol,
838 bool useSpecialFloats,
839 unsigned int precision);
840 int write(Value
const& root, std::ostream* sout)
override;
842 void writeValue(Value
const& value);
843 void writeArrayValue(Value
const& value);
844 bool isMultineArray(Value
const& value);
845 void pushValue(std::string
const& value);
847 void writeWithIndent(std::string
const& value);
850 void writeCommentBeforeValue(Value
const& root);
851 void writeCommentAfterValueOnSameLine(Value
const& root);
852 static bool hasCommentForValue(
const Value& value);
854 typedef std::vector<std::string> ChildValues;
856 ChildValues childValues_;
857 std::string indentString_;
859 std::string indentation_;
860 CommentStyle::Enum cs_;
861 std::string colonSymbol_;
862 std::string nullSymbol_;
863 std::string endingLineFeedSymbol_;
864 bool addChildValues_ : 1;
866 bool useSpecialFloats_ : 1;
867 unsigned int precision_;
869 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
870 std::string
const& indentation,
871 CommentStyle::Enum cs,
872 std::string
const& colonSymbol,
873 std::string
const& nullSymbol,
874 std::string
const& endingLineFeedSymbol,
875 bool useSpecialFloats,
876 unsigned int precision)
878 , indentation_(indentation)
880 , colonSymbol_(colonSymbol)
881 , nullSymbol_(nullSymbol)
882 , endingLineFeedSymbol_(endingLineFeedSymbol)
883 , addChildValues_(false)
885 , useSpecialFloats_(useSpecialFloats)
886 , precision_(precision)
889 int BuiltStyledStreamWriter::write(Value
const& root, std::ostream* sout)
892 addChildValues_ =
false;
895 writeCommentBeforeValue(root);
896 if (!indented_) writeIndent();
899 writeCommentAfterValueOnSameLine(root);
900 *sout_ << endingLineFeedSymbol_;
904 void BuiltStyledStreamWriter::writeValue(Value
const& value) {
905 switch (value.type()) {
907 pushValue(nullSymbol_);
916 pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_));
923 bool ok = value.getString(&str, &end);
932 writeArrayValue(value);
939 writeWithIndent(
"{");
941 Value::Members::iterator it = members.begin();
943 std::string
const& name = *it;
944 Value
const& childValue = value[name];
945 writeCommentBeforeValue(childValue);
947 *sout_ << colonSymbol_;
948 writeValue(childValue);
949 if (++it == members.end()) {
950 writeCommentAfterValueOnSameLine(childValue);
954 writeCommentAfterValueOnSameLine(childValue);
957 writeWithIndent(
"}");
963 void BuiltStyledStreamWriter::writeArrayValue(Value
const& value) {
964 unsigned size = value.size();
968 bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
970 writeWithIndent(
"[");
972 bool hasChildValue = !childValues_.empty();
975 Value
const& childValue = value[index];
976 writeCommentBeforeValue(childValue);
978 writeWithIndent(childValues_[index]);
980 if (!indented_) writeIndent();
982 writeValue(childValue);
985 if (++index == size) {
986 writeCommentAfterValueOnSameLine(childValue);
990 writeCommentAfterValueOnSameLine(childValue);
993 writeWithIndent(
"]");
996 assert(childValues_.size() == size);
998 if (!indentation_.empty()) *sout_ <<
" ";
999 for (
unsigned index = 0; index < size; ++index) {
1002 *sout_ << childValues_[index];
1004 if (!indentation_.empty()) *sout_ <<
" ";
1010 bool BuiltStyledStreamWriter::isMultineArray(Value
const& value) {
1011 int size = value.size();
1012 bool isMultiLine = size * 3 >= rightMargin_;
1013 childValues_.clear();
1014 for (
int index = 0; index < size && !isMultiLine; ++index) {
1015 Value
const& childValue = value[index];
1016 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
1017 childValue.size() > 0);
1021 childValues_.reserve(size);
1022 addChildValues_ =
true;
1023 int lineLength = 4 + (size - 1) * 2;
1024 for (
int index = 0; index < size; ++index) {
1025 if (hasCommentForValue(value[index])) {
1028 writeValue(value[index]);
1029 lineLength += int(childValues_[index].length());
1031 addChildValues_ =
false;
1032 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1037 void BuiltStyledStreamWriter::pushValue(std::string
const& value) {
1038 if (addChildValues_)
1039 childValues_.push_back(value);
1044 void BuiltStyledStreamWriter::writeIndent() {
1050 if (!indentation_.empty()) {
1052 *sout_ <<
'\n' << indentString_;
1056 void BuiltStyledStreamWriter::writeWithIndent(std::string
const& value) {
1057 if (!indented_) writeIndent();
1062 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1064 void BuiltStyledStreamWriter::unindent() {
1065 assert(indentString_.size() >= indentation_.size());
1066 indentString_.resize(indentString_.size() - indentation_.size());
1069 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value
const& root) {
1070 if (cs_ == CommentStyle::None)
return;
1074 if (!indented_) writeIndent();
1075 const std::string& comment = root.getComment(
commentBefore);
1076 std::string::const_iterator iter = comment.begin();
1077 while (iter != comment.end()) {
1079 if (*iter ==
'\n' &&
1080 (iter != comment.end() && *(iter + 1) ==
'/'))
1082 *sout_ << indentString_;
1088 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value
const& root) {
1089 if (cs_ == CommentStyle::None)
return;
1100 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1120 setDefaults(&settings_);
1126 std::string indentation = settings_[
"indentation"].asString();
1127 std::string cs_str = settings_[
"commentStyle"].asString();
1128 bool eyc = settings_[
"enableYAMLCompatibility"].asBool();
1129 bool dnp = settings_[
"dropNullPlaceholders"].asBool();
1130 bool usf = settings_[
"useSpecialFloats"].asBool();
1131 unsigned int pre = settings_[
"precision"].asUInt();
1132 CommentStyle::Enum cs = CommentStyle::All;
1133 if (cs_str ==
"All") {
1134 cs = CommentStyle::All;
1135 }
else if (cs_str ==
"None") {
1136 cs = CommentStyle::None;
1140 std::string colonSymbol =
" : ";
1143 }
else if (indentation.empty()) {
1146 std::string nullSymbol =
"null";
1150 if (pre > 17) pre = 17;
1151 std::string endingLineFeedSymbol =
"";
1152 return new BuiltStyledStreamWriter(
1154 colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
1158 valid_keys->clear();
1159 valid_keys->insert(
"indentation");
1160 valid_keys->insert(
"commentStyle");
1161 valid_keys->insert(
"enableYAMLCompatibility");
1162 valid_keys->insert(
"dropNullPlaceholders");
1163 valid_keys->insert(
"useSpecialFloats");
1164 valid_keys->insert(
"precision");
1169 if (!invalid) invalid = &my_invalid;
1171 std::set<std::string> valid_keys;
1174 size_t n = keys.size();
1175 for (
size_t i = 0; i < n; ++i) {
1176 std::string
const& key = keys[i];
1177 if (valid_keys.find(key) == valid_keys.end()) {
1178 inv[key] = settings_[key];
1181 return 0u == inv.
size();
1185 return settings_[key];
1191 (*settings)[
"commentStyle"] =
"All";
1192 (*settings)[
"indentation"] =
"\t";
1193 (*settings)[
"enableYAMLCompatibility"] =
false;
1194 (*settings)[
"dropNullPlaceholders"] =
false;
1195 (*settings)[
"useSpecialFloats"] =
false;
1196 (*settings)[
"precision"] = 17;
1201 std::ostringstream sout;
1203 writer->write(root, &sout);
1210 writer->write(root, &sout);