6 #if !defined(JSON_IS_AMALGAMATION)
9 #endif // if !defined(JSON_IS_AMALGAMATION)
18 #if __cplusplus >= 201103L
23 #define isnan std::isnan
26 #if !defined(isfinite)
27 #define isfinite std::isfinite
40 #if !defined(isfinite)
42 #define isfinite _finite
45 #if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
46 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
47 #endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
51 #if defined(__sun) && defined(__SVR4) // Solaris
52 #if !defined(isfinite)
54 #define isfinite finite
59 #if !defined(isfinite)
60 #if defined(__ia64) && !defined(finite)
62 ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
69 #define isnan(x) (x != x)
72 #if !defined(__APPLE__)
73 #if !defined(isfinite)
74 #define isfinite finite
81 #pragma warning(disable : 4996)
86 #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
94 char* current = buffer +
sizeof(buffer);
98 }
else if (value < 0) {
104 assert(current >= buffer);
110 char* current = buffer +
sizeof(buffer);
112 assert(current >= buffer);
116 #if defined(JSON_HAS_INT64)
122 #endif // # if defined(JSON_HAS_INT64)
131 static const char*
const reps[2][3] = {{
"NaN",
"-Infinity",
"Infinity"},
132 {
"null",
"-1e+9999",
"1e+9999"}};
133 return reps[useSpecialFloats ? 0 : 1]
134 [
isnan(value) ? 0 : (value < 0) ? 1 : 2];
137 String buffer(
size_t(36),
'\0');
140 &*buffer.begin(), buffer.size(),
144 auto wouldPrint = static_cast<size_t>(len);
145 if (wouldPrint >= buffer.size()) {
146 buffer.resize(wouldPrint + 1);
149 buffer.resize(wouldPrint);
162 if (buffer.find(
'.') == buffer.npos && buffer.find(
'e') == buffer.npos) {
171 return valueToString(value,
false, precision, precisionType);
179 char const*
const end = s + n;
180 for (
char const* cur = s; cur < end; ++cur) {
181 if (*cur ==
'\\' || *cur ==
'\"' ||
182 static_cast<unsigned char>(*cur) <
' ' ||
183 static_cast<unsigned char>(*cur) >= 0x80)
190 const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
192 unsigned int firstByte = static_cast<unsigned char>(*s);
194 if (firstByte < 0x80)
197 if (firstByte < 0xE0) {
199 return REPLACEMENT_CHARACTER;
201 unsigned int calculated =
202 ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
205 return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
208 if (firstByte < 0xF0) {
210 return REPLACEMENT_CHARACTER;
212 unsigned int calculated = ((firstByte & 0x0F) << 12) |
213 ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
214 (static_cast<unsigned int>(s[2]) & 0x3F);
218 if (calculated >= 0xD800 && calculated <= 0xDFFF)
219 return REPLACEMENT_CHARACTER;
221 return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
224 if (firstByte < 0xF8) {
226 return REPLACEMENT_CHARACTER;
228 unsigned int calculated = ((firstByte & 0x07) << 18) |
229 ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
230 ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
231 (static_cast<unsigned int>(s[3]) & 0x3F);
234 return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
237 return REPLACEMENT_CHARACTER;
240 static const char hex2[] =
"000102030405060708090a0b0c0d0e0f"
241 "101112131415161718191a1b1c1d1e1f"
242 "202122232425262728292a2b2c2d2e2f"
243 "303132333435363738393a3b3c3d3e3f"
244 "404142434445464748494a4b4c4d4e4f"
245 "505152535455565758595a5b5c5d5e5f"
246 "606162636465666768696a6b6c6d6e6f"
247 "707172737475767778797a7b7c7d7e7f"
248 "808182838485868788898a8b8c8d8e8f"
249 "909192939495969798999a9b9c9d9e9f"
250 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
251 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
252 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
253 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
254 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
255 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
258 const unsigned int hi = (x >> 8) & 0xff;
259 const unsigned int lo = x & 0xff;
261 result[0] =
hex2[2 * hi];
262 result[1] =
hex2[2 * hi + 1];
263 result[2] =
hex2[2 * lo];
264 result[3] =
hex2[2 * lo + 1];
269 bool emitUTF8 =
false) {
270 if (value ==
nullptr)
274 return String(
"\"") + value +
"\"";
278 String::size_type maxsize = length * 2 + 3;
280 result.reserve(maxsize);
282 char const* end = value + length;
283 for (
const char* c = value; c != end; ++c) {
319 const unsigned int FIRST_NON_CONTROL_CODEPOINT = 0x20;
320 const unsigned int LAST_NON_CONTROL_CODEPOINT = 0x7F;
321 const unsigned int FIRST_SURROGATE_PAIR_CODEPOINT = 0x10000;
324 if (FIRST_NON_CONTROL_CODEPOINT <= codepoint &&
325 codepoint <= LAST_NON_CONTROL_CODEPOINT) {
326 result += static_cast<char>(codepoint);
327 }
else if (codepoint <
328 FIRST_SURROGATE_PAIR_CODEPOINT) {
334 codepoint -= FIRST_SURROGATE_PAIR_CODEPOINT;
336 result +=
toHex16Bit((codepoint >> 10) + 0xD800);
338 result +=
toHex16Bit((codepoint & 0x3FF) + 0xDC00);
354 Writer::~Writer() =
default;
359 FastWriter::FastWriter()
363 void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ =
true; }
365 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ =
true; }
367 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ =
true; }
369 String FastWriter::write(
const Value& root) {
372 if (!omitEndingLineFeed_)
377 void FastWriter::writeValue(
const Value& value) {
378 switch (value.type()) {
380 if (!dropNullPlaceholders_)
396 bool ok = value.getString(&str, &end);
407 for (
ArrayIndex index = 0; index < size; ++index) {
410 writeValue(value[index]);
417 for (
auto it = members.begin(); it != members.end(); ++it) {
419 if (it != members.begin())
422 static_cast<unsigned>(name.length()));
423 document_ += yamlCompatibilityEnabled_ ?
": " :
":";
424 writeValue(value[name]);
434 StyledWriter::StyledWriter() =
default;
436 String StyledWriter::write(
const Value& root) {
438 addChildValues_ =
false;
439 indentString_.clear();
440 writeCommentBeforeValue(root);
442 writeCommentAfterValueOnSameLine(root);
447 void StyledWriter::writeValue(
const Value& value) {
448 switch (value.type()) {
465 bool ok = value.getString(&str, &end);
476 writeArrayValue(value);
483 writeWithIndent(
"{");
485 auto it = members.begin();
488 const Value& childValue = value[name];
489 writeCommentBeforeValue(childValue);
492 writeValue(childValue);
493 if (++it == members.end()) {
494 writeCommentAfterValueOnSameLine(childValue);
498 writeCommentAfterValueOnSameLine(childValue);
501 writeWithIndent(
"}");
507 void StyledWriter::writeArrayValue(
const Value& value) {
508 unsigned size = value.size();
512 bool isArrayMultiLine = isMultilineArray(value);
513 if (isArrayMultiLine) {
514 writeWithIndent(
"[");
516 bool hasChildValue = !childValues_.empty();
519 const Value& childValue = value[index];
520 writeCommentBeforeValue(childValue);
522 writeWithIndent(childValues_[index]);
525 writeValue(childValue);
527 if (++index == size) {
528 writeCommentAfterValueOnSameLine(childValue);
532 writeCommentAfterValueOnSameLine(childValue);
535 writeWithIndent(
"]");
538 assert(childValues_.size() == size);
540 for (
unsigned index = 0; index < size; ++index) {
543 document_ += childValues_[index];
550 bool StyledWriter::isMultilineArray(
const Value& value) {
552 bool isMultiLine = size * 3 >= rightMargin_;
553 childValues_.clear();
554 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
555 const Value& childValue = value[index];
556 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
557 !childValue.empty());
561 childValues_.reserve(size);
562 addChildValues_ =
true;
564 for (
ArrayIndex index = 0; index < size; ++index) {
565 if (hasCommentForValue(value[index])) {
568 writeValue(value[index]);
569 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
571 addChildValues_ =
false;
572 isMultiLine = isMultiLine || lineLength >= rightMargin_;
577 void StyledWriter::pushValue(
const String& value) {
579 childValues_.push_back(value);
584 void StyledWriter::writeIndent() {
585 if (!document_.empty()) {
586 char last = document_[document_.length() - 1];
592 document_ += indentString_;
595 void StyledWriter::writeWithIndent(
const String& value) {
600 void StyledWriter::indent() { indentString_ +=
String(indentSize_,
' '); }
602 void StyledWriter::unindent() {
603 assert(indentString_.size() >= indentSize_);
604 indentString_.resize(indentString_.size() - indentSize_);
607 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
614 String::const_iterator iter = comment.begin();
615 while (iter != comment.end()) {
617 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
626 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
637 bool StyledWriter::hasCommentForValue(
const Value& value) {
646 StyledStreamWriter::StyledStreamWriter(
String indentation)
647 : document_(nullptr), indentation_(std::move(indentation)),
648 addChildValues_(), indented_(false) {}
650 void StyledStreamWriter::write(
OStream& out,
const Value& root) {
652 addChildValues_ =
false;
653 indentString_.clear();
655 writeCommentBeforeValue(root);
660 writeCommentAfterValueOnSameLine(root);
665 void StyledStreamWriter::writeValue(
const Value& value) {
666 switch (value.type()) {
683 bool ok = value.getString(&str, &end);
694 writeArrayValue(value);
697 Value::Members members(value.getMemberNames());
701 writeWithIndent(
"{");
703 auto it = members.begin();
706 const Value& childValue = value[name];
707 writeCommentBeforeValue(childValue);
710 writeValue(childValue);
711 if (++it == members.end()) {
712 writeCommentAfterValueOnSameLine(childValue);
716 writeCommentAfterValueOnSameLine(childValue);
719 writeWithIndent(
"}");
725 void StyledStreamWriter::writeArrayValue(
const Value& value) {
726 unsigned size = value.size();
730 bool isArrayMultiLine = isMultilineArray(value);
731 if (isArrayMultiLine) {
732 writeWithIndent(
"[");
734 bool hasChildValue = !childValues_.empty();
737 const Value& childValue = value[index];
738 writeCommentBeforeValue(childValue);
740 writeWithIndent(childValues_[index]);
745 writeValue(childValue);
748 if (++index == size) {
749 writeCommentAfterValueOnSameLine(childValue);
753 writeCommentAfterValueOnSameLine(childValue);
756 writeWithIndent(
"]");
759 assert(childValues_.size() == size);
761 for (
unsigned index = 0; index < size; ++index) {
764 *document_ << childValues_[index];
771 bool StyledStreamWriter::isMultilineArray(
const Value& value) {
773 bool isMultiLine = size * 3 >= rightMargin_;
774 childValues_.clear();
775 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
776 const Value& childValue = value[index];
777 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
778 !childValue.empty());
782 childValues_.reserve(size);
783 addChildValues_ =
true;
785 for (
ArrayIndex index = 0; index < size; ++index) {
786 if (hasCommentForValue(value[index])) {
789 writeValue(value[index]);
790 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
792 addChildValues_ =
false;
793 isMultiLine = isMultiLine || lineLength >= rightMargin_;
798 void StyledStreamWriter::pushValue(
const String& value) {
800 childValues_.push_back(value);
805 void StyledStreamWriter::writeIndent() {
810 *document_ <<
'\n' << indentString_;
813 void StyledStreamWriter::writeWithIndent(
const String& value) {
820 void StyledStreamWriter::indent() { indentString_ += indentation_; }
822 void StyledStreamWriter::unindent() {
823 assert(indentString_.size() >= indentation_.size());
824 indentString_.resize(indentString_.size() - indentation_.size());
827 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
834 String::const_iterator iter = comment.begin();
835 while (iter != comment.end()) {
837 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
839 *document_ << indentString_;
845 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
856 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
866 struct CommentStyle {
875 struct BuiltStyledStreamWriter :
public StreamWriter {
876 BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs,
878 String endingLineFeedSymbol,
bool useSpecialFloats,
879 bool emitUTF8,
unsigned int precision,
881 int write(Value
const& root,
OStream* sout)
override;
884 void writeValue(Value
const& value);
885 void writeArrayValue(Value
const& value);
886 bool isMultilineArray(Value
const& value);
887 void pushValue(
String const& value);
889 void writeWithIndent(
String const& value);
892 void writeCommentBeforeValue(Value
const& root);
893 void writeCommentAfterValueOnSameLine(Value
const& root);
894 static bool hasCommentForValue(
const Value& value);
896 using ChildValues = std::vector<String>;
898 ChildValues childValues_;
900 unsigned int rightMargin_;
902 CommentStyle::Enum cs_;
905 String endingLineFeedSymbol_;
906 bool addChildValues_ : 1;
908 bool useSpecialFloats_ : 1;
910 unsigned int precision_;
913 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
914 String indentation, CommentStyle::Enum cs,
String colonSymbol,
915 String nullSymbol,
String endingLineFeedSymbol,
bool useSpecialFloats,
916 bool emitUTF8,
unsigned int precision,
PrecisionType precisionType)
917 : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
918 colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
919 endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
920 addChildValues_(false), indented_(false),
921 useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
922 precision_(precision), precisionType_(precisionType) {}
923 int BuiltStyledStreamWriter::write(Value
const& root,
OStream* sout) {
925 addChildValues_ =
false;
927 indentString_.clear();
928 writeCommentBeforeValue(root);
933 writeCommentAfterValueOnSameLine(root);
934 *sout_ << endingLineFeedSymbol_;
938 void BuiltStyledStreamWriter::writeValue(Value
const& value) {
939 switch (value.type()) {
941 pushValue(nullSymbol_);
950 pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_,
957 bool ok = value.getString(&str, &end);
969 writeArrayValue(value);
972 Value::Members members(value.getMemberNames());
976 writeWithIndent(
"{");
978 auto it = members.begin();
981 Value
const& childValue = value[name];
982 writeCommentBeforeValue(childValue);
984 name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
985 *sout_ << colonSymbol_;
986 writeValue(childValue);
987 if (++it == members.end()) {
988 writeCommentAfterValueOnSameLine(childValue);
992 writeCommentAfterValueOnSameLine(childValue);
995 writeWithIndent(
"}");
1001 void BuiltStyledStreamWriter::writeArrayValue(Value
const& value) {
1002 unsigned size = value.size();
1006 bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
1008 writeWithIndent(
"[");
1010 bool hasChildValue = !childValues_.empty();
1013 Value
const& childValue = value[index];
1014 writeCommentBeforeValue(childValue);
1016 writeWithIndent(childValues_[index]);
1021 writeValue(childValue);
1024 if (++index == size) {
1025 writeCommentAfterValueOnSameLine(childValue);
1029 writeCommentAfterValueOnSameLine(childValue);
1032 writeWithIndent(
"]");
1035 assert(childValues_.size() == size);
1037 if (!indentation_.empty())
1039 for (
unsigned index = 0; index < size; ++index) {
1041 *sout_ << ((!indentation_.empty()) ?
", " :
",");
1042 *sout_ << childValues_[index];
1044 if (!indentation_.empty())
1051 bool BuiltStyledStreamWriter::isMultilineArray(Value
const& value) {
1053 bool isMultiLine = size * 3 >= rightMargin_;
1054 childValues_.clear();
1055 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
1056 Value
const& childValue = value[index];
1057 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
1058 !childValue.empty());
1062 childValues_.reserve(size);
1063 addChildValues_ =
true;
1065 for (
ArrayIndex index = 0; index < size; ++index) {
1066 if (hasCommentForValue(value[index])) {
1069 writeValue(value[index]);
1070 lineLength += static_cast<ArrayIndex>(childValues_[index].length());
1072 addChildValues_ =
false;
1073 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1078 void BuiltStyledStreamWriter::pushValue(
String const& value) {
1079 if (addChildValues_)
1080 childValues_.push_back(value);
1085 void BuiltStyledStreamWriter::writeIndent() {
1091 if (!indentation_.empty()) {
1093 *sout_ <<
'\n' << indentString_;
1097 void BuiltStyledStreamWriter::writeWithIndent(
String const& value) {
1104 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1106 void BuiltStyledStreamWriter::unindent() {
1107 assert(indentString_.size() >= indentation_.size());
1108 indentString_.resize(indentString_.size() - indentation_.size());
1111 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value
const& root) {
1112 if (cs_ == CommentStyle::None)
1120 String::const_iterator iter = comment.begin();
1121 while (iter != comment.end()) {
1123 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
1125 *sout_ << indentString_;
1131 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
1132 Value
const& root) {
1133 if (cs_ == CommentStyle::None)
1145 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1154 StreamWriter::StreamWriter() : sout_(nullptr) {}
1168 CommentStyle::Enum cs = CommentStyle::All;
1169 if (cs_str ==
"All") {
1170 cs = CommentStyle::All;
1171 }
else if (cs_str ==
"None") {
1172 cs = CommentStyle::None;
1174 throwRuntimeError(
"commentStyle must be 'All' or 'None'");
1177 if (pt_str ==
"significant") {
1179 }
else if (pt_str ==
"decimal") {
1182 throwRuntimeError(
"precisionType must be 'significant' or 'decimal'");
1184 String colonSymbol =
" : ";
1187 }
else if (indentation.empty()) {
1190 String nullSymbol =
"null";
1196 String endingLineFeedSymbol;
1197 return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
1198 endingLineFeedSymbol, usf, emitUTF8, pre,
1202 valid_keys->clear();
1203 valid_keys->insert(
"indentation");
1204 valid_keys->insert(
"commentStyle");
1205 valid_keys->insert(
"enableYAMLCompatibility");
1206 valid_keys->insert(
"dropNullPlaceholders");
1207 valid_keys->insert(
"useSpecialFloats");
1208 valid_keys->insert(
"emitUTF8");
1209 valid_keys->insert(
"precision");
1210 valid_keys->insert(
"precisionType");
1215 invalid = &my_invalid;
1217 std::set<String> valid_keys;
1220 size_t n = keys.size();
1221 for (
size_t i = 0; i < n; ++i) {
1222 String const& key = keys[i];
1223 if (valid_keys.find(key) == valid_keys.end()) {
1235 (*settings)[
"commentStyle"] =
"All";
1236 (*settings)[
"indentation"] =
"\t";
1237 (*settings)[
"enableYAMLCompatibility"] =
false;
1238 (*settings)[
"dropNullPlaceholders"] =
false;
1239 (*settings)[
"useSpecialFloats"] =
false;
1240 (*settings)[
"emitUTF8"] =
false;
1241 (*settings)[
"precision"] = 17;
1242 (*settings)[
"precisionType"] =
"significant";
1249 writer->write(root, &sout);
1256 writer->write(root, &sout);