6#if !defined(JSON_IS_AMALGAMATION)
20#if __cplusplus >= 201103L
25#define isnan std::isnan
29#define isfinite std::isfinite
44#define isfinite _finite
47#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
48#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
53#if defined(__sun) && defined(__SVR4)
56#define isfinite finite
62#if defined(__ia64) && !defined(finite)
64 ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
71#define isnan(x) ((x) != (x))
74#if !defined(__APPLE__)
76#define isfinite finite
83#pragma warning(disable : 4996)
88#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
96 char* current = buffer +
sizeof(buffer);
100 }
else if (value < 0) {
106 assert(current >= buffer);
112 char* current = buffer +
sizeof(buffer);
114 assert(current >= buffer);
118#if defined(JSON_HAS_INT64)
128 unsigned int precision, PrecisionType precisionType) {
133 static const char*
const reps[2][3] = {{
"NaN",
"-Infinity",
"Infinity"},
134 {
"null",
"-1e+9999",
"1e+9999"}};
135 return reps[useSpecialFloats ? 0 : 1][
isnan(value) ? 0
140 String buffer(
size_t(36),
'\0');
143 &*buffer.begin(), buffer.size(),
147 auto wouldPrint =
static_cast<size_t>(len);
148 if (wouldPrint >= buffer.size()) {
149 buffer.resize(wouldPrint + 1);
152 buffer.resize(wouldPrint);
160 if (buffer.find(
'.') == buffer.npos && buffer.find(
'e') == buffer.npos) {
176 return valueToString(value,
false, precision, precisionType);
184 return std::any_of(s, s + n, [](
unsigned char c) {
185 return c ==
'\\' || c ==
'"' || c < 0x20 || c > 0x7F;
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;
240static 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 result +=
static_cast<char>(ch);
277 bool emitUTF8 =
false) {
278 if (value ==
nullptr)
282 return String(
"\"") + value +
"\"";
286 String::size_type maxsize = length * 2 + 3;
288 result.reserve(maxsize);
290 char const* end = value + length;
291 for (
const char* c = value; c != end; ++c) {
324 unsigned codepoint =
static_cast<unsigned char>(*c);
325 if (codepoint < 0x20) {
332 if (codepoint < 0x20) {
334 }
else if (codepoint < 0x80) {
336 }
else if (codepoint < 0x10000) {
341 codepoint -= 0x10000;
342 appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
343 appendHex(result, 0xdc00 + (codepoint & 0x3ff));
381 if (!omitEndingLineFeed_)
386void FastWriter::writeValue(
const Value& value) {
387 switch (value.
type()) {
389 if (!dropNullPlaceholders_)
416 for (
ArrayIndex index = 0; index < size; ++index) {
419 writeValue(value[index]);
426 for (
auto it = members.begin(); it != members.end(); ++it) {
428 if (it != members.begin())
431 document_ += yamlCompatibilityEnabled_ ?
": " :
":";
432 writeValue(value[name]);
446 addChildValues_ =
false;
447 indentString_.clear();
448 writeCommentBeforeValue(root);
450 writeCommentAfterValueOnSameLine(root);
455void StyledWriter::writeValue(
const Value& value) {
456 switch (value.
type()) {
484 writeArrayValue(value);
491 writeWithIndent(
"{");
493 auto it = members.begin();
496 const Value& childValue = value[name];
497 writeCommentBeforeValue(childValue);
500 writeValue(childValue);
501 if (++it == members.end()) {
502 writeCommentAfterValueOnSameLine(childValue);
506 writeCommentAfterValueOnSameLine(childValue);
509 writeWithIndent(
"}");
515void StyledWriter::writeArrayValue(
const Value& value) {
516 size_t size = value.size();
520 bool isArrayMultiLine = isMultilineArray(value);
521 if (isArrayMultiLine) {
522 writeWithIndent(
"[");
524 bool hasChildValue = !childValues_.empty();
527 const Value& childValue = value[index];
528 writeCommentBeforeValue(childValue);
530 writeWithIndent(childValues_[index]);
533 writeValue(childValue);
535 if (++index == size) {
536 writeCommentAfterValueOnSameLine(childValue);
540 writeCommentAfterValueOnSameLine(childValue);
543 writeWithIndent(
"]");
546 assert(childValues_.size() == size);
548 for (
size_t index = 0; index < size; ++index) {
551 document_ += childValues_[index];
558bool StyledWriter::isMultilineArray(
const Value& value) {
560 bool isMultiLine = size * 3 >= rightMargin_;
561 childValues_.clear();
562 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
563 const Value& childValue = value[index];
564 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
565 !childValue.empty());
569 childValues_.reserve(size);
570 addChildValues_ =
true;
572 for (
ArrayIndex index = 0; index < size; ++index) {
573 if (hasCommentForValue(value[index])) {
576 writeValue(value[index]);
577 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
579 addChildValues_ =
false;
580 isMultiLine = isMultiLine || lineLength >= rightMargin_;
585void StyledWriter::pushValue(
const String& value) {
587 childValues_.push_back(value);
592void StyledWriter::writeIndent() {
593 if (!document_.empty()) {
594 char last = document_[document_.length() - 1];
600 document_ += indentString_;
603void StyledWriter::writeWithIndent(
const String& value) {
608void StyledWriter::indent() { indentString_ +=
String(indentSize_,
' '); }
610void StyledWriter::unindent() {
611 assert(indentString_.size() >= indentSize_);
612 indentString_.resize(indentString_.size() - indentSize_);
615void StyledWriter::writeCommentBeforeValue(
const Value& root) {
622 String::const_iterator iter = comment.begin();
623 while (iter != comment.end()) {
625 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
634void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
645bool StyledWriter::hasCommentForValue(
const Value& value) {
655 : document_(nullptr), indentation_(std::move(indentation)),
656 addChildValues_(), indented_(false) {}
660 addChildValues_ =
false;
661 indentString_.clear();
663 writeCommentBeforeValue(root);
668 writeCommentAfterValueOnSameLine(root);
673void StyledStreamWriter::writeValue(
const Value& value) {
674 switch (value.
type()) {
702 writeArrayValue(value);
709 writeWithIndent(
"{");
711 auto it = members.begin();
714 const Value& childValue = value[name];
715 writeCommentBeforeValue(childValue);
718 writeValue(childValue);
719 if (++it == members.end()) {
720 writeCommentAfterValueOnSameLine(childValue);
724 writeCommentAfterValueOnSameLine(childValue);
727 writeWithIndent(
"}");
733void StyledStreamWriter::writeArrayValue(
const Value& value) {
734 unsigned size = value.size();
738 bool isArrayMultiLine = isMultilineArray(value);
739 if (isArrayMultiLine) {
740 writeWithIndent(
"[");
742 bool hasChildValue = !childValues_.empty();
745 const Value& childValue = value[index];
746 writeCommentBeforeValue(childValue);
748 writeWithIndent(childValues_[index]);
753 writeValue(childValue);
756 if (++index == size) {
757 writeCommentAfterValueOnSameLine(childValue);
761 writeCommentAfterValueOnSameLine(childValue);
764 writeWithIndent(
"]");
767 assert(childValues_.size() == size);
769 for (
unsigned index = 0; index < size; ++index) {
772 *document_ << childValues_[index];
779bool StyledStreamWriter::isMultilineArray(
const Value& value) {
781 bool isMultiLine = size * 3 >= rightMargin_;
782 childValues_.clear();
783 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
784 const Value& childValue = value[index];
785 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
786 !childValue.empty());
790 childValues_.reserve(size);
791 addChildValues_ =
true;
793 for (
ArrayIndex index = 0; index < size; ++index) {
794 if (hasCommentForValue(value[index])) {
797 writeValue(value[index]);
798 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
800 addChildValues_ =
false;
801 isMultiLine = isMultiLine || lineLength >= rightMargin_;
806void StyledStreamWriter::pushValue(
const String& value) {
808 childValues_.push_back(value);
813void StyledStreamWriter::writeIndent() {
818 *document_ <<
'\n' << indentString_;
821void StyledStreamWriter::writeWithIndent(
const String& value) {
828void StyledStreamWriter::indent() { indentString_ += indentation_; }
830void StyledStreamWriter::unindent() {
831 assert(indentString_.size() >= indentation_.size());
832 indentString_.resize(indentString_.size() - indentation_.size());
835void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
842 String::const_iterator iter = comment.begin();
843 while (iter != comment.end()) {
845 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
847 *document_ << indentString_;
853void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
864bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
884 BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs,
886 String endingLineFeedSymbol,
bool useSpecialFloats,
887 bool emitUTF8,
unsigned int precision,
889 int write(Value
const& root,
OStream* sout)
override;
892 void writeValue(Value
const& value);
893 void writeArrayValue(Value
const& value);
894 bool isMultilineArray(Value
const& value);
895 void pushValue(
String const& value);
897 void writeWithIndent(
String const& value);
900 void writeCommentBeforeValue(Value
const& root);
901 void writeCommentAfterValueOnSameLine(Value
const& root);
902 static bool hasCommentForValue(
const Value& value);
904 using ChildValues = std::vector<String>;
906 ChildValues childValues_;
908 unsigned int rightMargin_;
910 CommentStyle::Enum cs_;
913 String endingLineFeedSymbol_;
914 bool addChildValues_ : 1;
916 bool useSpecialFloats_ : 1;
918 unsigned int precision_;
921BuiltStyledStreamWriter::BuiltStyledStreamWriter(
922 String indentation, CommentStyle::Enum cs,
String colonSymbol,
923 String nullSymbol,
String endingLineFeedSymbol,
bool useSpecialFloats,
924 bool emitUTF8,
unsigned int precision,
PrecisionType precisionType)
925 : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
926 colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
927 endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
928 addChildValues_(false), indented_(false),
929 useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
930 precision_(precision), precisionType_(precisionType) {}
931int BuiltStyledStreamWriter::write(
Value const& root,
OStream* sout) {
933 addChildValues_ =
false;
935 indentString_.clear();
936 writeCommentBeforeValue(root);
941 writeCommentAfterValueOnSameLine(root);
942 *
sout_ << endingLineFeedSymbol_;
946void BuiltStyledStreamWriter::writeValue(
Value const& value) {
947 switch (value.type()) {
949 pushValue(nullSymbol_);
958 pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_,
965 bool ok = value.getString(&str, &end);
977 writeArrayValue(value);
984 writeWithIndent(
"{");
986 auto it = members.begin();
989 Value
const& childValue = value[name];
990 writeCommentBeforeValue(childValue);
993 *
sout_ << colonSymbol_;
994 writeValue(childValue);
995 if (++it == members.end()) {
996 writeCommentAfterValueOnSameLine(childValue);
1000 writeCommentAfterValueOnSameLine(childValue);
1003 writeWithIndent(
"}");
1009void BuiltStyledStreamWriter::writeArrayValue(
Value const& value) {
1010 unsigned size = value.size();
1014 bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
1016 writeWithIndent(
"[");
1018 bool hasChildValue = !childValues_.empty();
1021 Value
const& childValue = value[index];
1022 writeCommentBeforeValue(childValue);
1024 writeWithIndent(childValues_[index]);
1029 writeValue(childValue);
1032 if (++index == size) {
1033 writeCommentAfterValueOnSameLine(childValue);
1037 writeCommentAfterValueOnSameLine(childValue);
1040 writeWithIndent(
"]");
1043 assert(childValues_.size() == size);
1045 if (!indentation_.empty())
1047 for (
unsigned index = 0; index < size; ++index) {
1049 *
sout_ << ((!indentation_.empty()) ?
", " :
",");
1050 *
sout_ << childValues_[index];
1052 if (!indentation_.empty())
1059bool BuiltStyledStreamWriter::isMultilineArray(
Value const& value) {
1061 bool isMultiLine = size * 3 >= rightMargin_;
1062 childValues_.clear();
1063 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
1064 Value
const& childValue = value[index];
1065 isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
1066 !childValue.empty());
1070 childValues_.reserve(size);
1071 addChildValues_ =
true;
1073 for (
ArrayIndex index = 0; index < size; ++index) {
1074 if (hasCommentForValue(value[index])) {
1077 writeValue(value[index]);
1078 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
1080 addChildValues_ =
false;
1081 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1086void BuiltStyledStreamWriter::pushValue(
String const& value) {
1087 if (addChildValues_)
1088 childValues_.push_back(value);
1093void BuiltStyledStreamWriter::writeIndent() {
1099 if (!indentation_.empty()) {
1101 *
sout_ <<
'\n' << indentString_;
1105void BuiltStyledStreamWriter::writeWithIndent(
String const& value) {
1112void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1114void BuiltStyledStreamWriter::unindent() {
1115 assert(indentString_.size() >= indentation_.size());
1116 indentString_.resize(indentString_.size() - indentation_.size());
1119void BuiltStyledStreamWriter::writeCommentBeforeValue(
Value const& root) {
1120 if (cs_ == CommentStyle::None)
1128 String::const_iterator iter = comment.begin();
1129 while (iter != comment.end()) {
1131 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
1133 *
sout_ << indentString_;
1139void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
1140 Value const& root) {
1141 if (cs_ == CommentStyle::None)
1153bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1171 const bool eyc =
settings_[
"enableYAMLCompatibility"].asBool();
1172 const bool dnp =
settings_[
"dropNullPlaceholders"].asBool();
1173 const bool usf =
settings_[
"useSpecialFloats"].asBool();
1174 const bool emitUTF8 =
settings_[
"emitUTF8"].asBool();
1175 unsigned int pre =
settings_[
"precision"].asUInt();
1176 CommentStyle::Enum cs = CommentStyle::All;
1177 if (cs_str ==
"All") {
1178 cs = CommentStyle::All;
1179 }
else if (cs_str ==
"None") {
1180 cs = CommentStyle::None;
1182 throwRuntimeError(
"commentStyle must be 'All' or 'None'");
1185 if (pt_str ==
"significant") {
1187 }
else if (pt_str ==
"decimal") {
1190 throwRuntimeError(
"precisionType must be 'significant' or 'decimal'");
1192 String colonSymbol =
" : ";
1195 }
else if (indentation.empty()) {
1198 String nullSymbol =
"null";
1204 String endingLineFeedSymbol;
1205 return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
1206 endingLineFeedSymbol, usf, emitUTF8, pre,
1211 static const auto& valid_keys = *
new std::set<String>{
1214 "enableYAMLCompatibility",
1215 "dropNullPlaceholders",
1222 auto key = si.name();
1223 if (valid_keys.count(key))
1226 (*invalid)[key] = *si;
1230 return invalid ? invalid->
empty() :
true;
1239 (*settings)[
"commentStyle"] =
"All";
1240 (*settings)[
"indentation"] =
"\t";
1241 (*settings)[
"enableYAMLCompatibility"] =
false;
1242 (*settings)[
"dropNullPlaceholders"] =
false;
1243 (*settings)[
"useSpecialFloats"] =
false;
1244 (*settings)[
"emitUTF8"] =
false;
1245 (*settings)[
"precision"] = 17;
1246 (*settings)[
"precisionType"] =
"significant";
1253 writer->
write(root, &sout);
1254 return std::move(sout).str();
1260 writer->
write(root, &sout);
String write(const Value &root) override
void dropNullPlaceholders()
Drop the "null" string from the writer's output for nullValues.
void enableYAMLCompatibility()
void omitEndingLineFeed()
A simple abstract factory.
virtual StreamWriter * newStreamWriter() const =0
Allocate a CharReader via operator new().
Build a StreamWriter implementation.
StreamWriter * newStreamWriter() const override
bool validate(Json::Value *invalid) const
static void setDefaults(Json::Value *settings)
Called by ctor, but you can use this to reset settings_.
Json::Value settings_
Configuration of this builder.
~StreamWriterBuilder() override
Value & operator[](const String &key)
A simple way to update a specific setting.
virtual int write(Value const &root, OStream *sout)=0
Write Value into document as configured in sub-class.
void write(OStream &out, const Value &root)
Serialize a Value in JSON format.
StyledStreamWriter(String indentation="\t")
String write(const Value &root) override
Serialize a Value in JSON format.
bool empty() const
Return true if empty array, empty object, or null; otherwise, false.
static constexpr LargestInt maxLargestInt
Maximum signed integer value that can be stored in a Json::Value.
ArrayIndex size() const
Number of values in array or object.
bool getString(char const **begin, char const **end) const
Get raw char* of string-value.
std::vector< String > Members
Members getMemberNames() const
Return a list of the member names.
LargestInt asLargestInt() const
LargestUInt asLargestUInt() const
static constexpr LargestInt minLargestInt
Minimum signed integer value that can be stored in a Json::Value.
JSON (JavaScript Object Notation).
std::basic_ostringstream< String::value_type, String::traits_type, String::allocator_type > OStringStream
static unsigned int utf8ToCodepoint(const char *&s, const char *e)
static void appendRaw(String &result, unsigned ch)
String writeString(StreamWriter::Factory const &factory, Value const &root)
Write into stringstream, then return string, for convenience.
Iter fixNumericLocale(Iter begin, Iter end)
Change ',' to '.
@ commentAfterOnSameLine
a comment just after a value on the same line
@ commentBefore
a comment placed on the line before a value
@ commentAfter
a comment on the line after a value (only make sense for
static String toHex16Bit(unsigned int x)
static bool doesAnyCharRequireEscaping(char const *s, size_t n)
String valueToQuotedString(const char *value)
static String valueToQuotedStringN(const char *value, size_t length, bool emitUTF8=false)
String valueToString(Int value)
@ stringValue
UTF-8 string value.
@ arrayValue
array value (ordered list)
@ intValue
signed integer value
@ objectValue
object value (collection of name/value pairs).
@ uintValue
unsigned integer value
OStream & operator<<(OStream &, const Value &root)
Output using the StyledStreamWriter.
std::auto_ptr< StreamWriter > StreamWriterPtr
static void appendHex(String &result, unsigned ch)
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision)
Return iterator that would be the new end of the range [begin,end), if we were to delete zeros in the...
std::basic_string< char, std::char_traits< char >, Allocator< char > > String
char[uintToStringBufferSize] UIntToStringBuffer
static void uintToString(LargestUInt value, char *¤t)
Converts an unsigned integer to string.
PrecisionType
Type of precision for formatting of real values.
@ decimalPlaces
we set max number of digits after "." in string
@ significantDigits
we set max number of significant digits in string