6 #if !defined(JSON_IS_AMALGAMATION) 9 #endif // if !defined(JSON_IS_AMALGAMATION) 20 #if __cplusplus >= 201103L 25 #define isnan std::isnan 28 #if !defined(isfinite) 29 #define isfinite std::isfinite 42 #if !defined(isfinite) 44 #define isfinite _finite 47 #if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES) 48 #define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1 49 #endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 53 #if defined(__sun) && defined(__SVR4) // Solaris 54 #if !defined(isfinite) 56 #define isfinite finite 61 #if !defined(isfinite) 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__) 75 #if !defined(isfinite) 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) 124 #endif // # if defined(JSON_HAS_INT64) 133 static const char*
const reps[2][3] = {{
"NaN",
"-Infinity",
"Infinity"},
134 {
"null",
"-1e+9999",
"1e+9999"}};
135 return reps[useSpecialFloats ? 0 : 1]
136 [
isnan(value) ? 0 : (value < 0) ? 1 : 2];
139 String buffer(
size_t(36),
'\0');
142 &*buffer.begin(), buffer.size(),
146 auto wouldPrint =
static_cast<size_t>(len);
147 if (wouldPrint >= buffer.size()) {
148 buffer.resize(wouldPrint + 1);
151 buffer.resize(wouldPrint);
159 if (buffer.find(
'.') == buffer.npos && buffer.find(
'e') == buffer.npos) {
175 return valueToString(value,
false, precision, precisionType);
183 return std::any_of(s, s + n, [](
unsigned char c) {
184 return c ==
'\\' || c ==
'"' || c < 0x20 || c > 0x7F;
189 const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
191 unsigned int firstByte =
static_cast<unsigned char>(*s);
193 if (firstByte < 0x80)
196 if (firstByte < 0xE0) {
198 return REPLACEMENT_CHARACTER;
200 unsigned int calculated =
201 ((firstByte & 0x1F) << 6) | (
static_cast<unsigned int>(s[1]) & 0x3F);
204 return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
207 if (firstByte < 0xF0) {
209 return REPLACEMENT_CHARACTER;
211 unsigned int calculated = ((firstByte & 0x0F) << 12) |
212 ((
static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
213 (static_cast<unsigned int>(s[2]) & 0x3F);
217 if (calculated >= 0xD800 && calculated <= 0xDFFF)
218 return REPLACEMENT_CHARACTER;
220 return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
223 if (firstByte < 0xF8) {
225 return REPLACEMENT_CHARACTER;
227 unsigned int calculated = ((firstByte & 0x07) << 18) |
228 ((
static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
229 ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
230 (
static_cast<unsigned int>(s[3]) & 0x3F);
233 return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
236 return REPLACEMENT_CHARACTER;
239 static const char hex2[] =
"000102030405060708090a0b0c0d0e0f" 240 "101112131415161718191a1b1c1d1e1f" 241 "202122232425262728292a2b2c2d2e2f" 242 "303132333435363738393a3b3c3d3e3f" 243 "404142434445464748494a4b4c4d4e4f" 244 "505152535455565758595a5b5c5d5e5f" 245 "606162636465666768696a6b6c6d6e6f" 246 "707172737475767778797a7b7c7d7e7f" 247 "808182838485868788898a8b8c8d8e8f" 248 "909192939495969798999a9b9c9d9e9f" 249 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 250 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" 251 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" 252 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" 253 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" 254 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
257 const unsigned int hi = (x >> 8) & 0xff;
258 const unsigned int lo = x & 0xff;
260 result[0] = hex2[2 * hi];
261 result[1] = hex2[2 * hi + 1];
262 result[2] = hex2[2 * lo];
263 result[3] = hex2[2 * lo + 1];
268 result +=
static_cast<char>(ch);
276 bool emitUTF8 =
false) {
277 if (value ==
nullptr)
281 return String(
"\"") + value +
"\"";
285 String::size_type maxsize = length * 2 + 3;
287 result.reserve(maxsize);
289 char const* end = value + length;
290 for (
const char* c = value; c != end; ++c) {
323 unsigned codepoint =
static_cast<unsigned char>(*c);
324 if (codepoint < 0x20) {
331 if (codepoint < 0x20) {
333 }
else if (codepoint < 0x80) {
335 }
else if (codepoint < 0x10000) {
340 codepoint -= 0x10000;
341 appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
342 appendHex(result, 0xdc00 + (codepoint & 0x3ff));
376 if (!omitEndingLineFeed_)
381 void FastWriter::writeValue(
const Value& value) {
382 switch (value.
type()) {
384 if (!dropNullPlaceholders_)
411 for (
ArrayIndex index = 0; index < size; ++index) {
414 writeValue(value[index]);
421 for (
auto it = members.begin(); it != members.end(); ++it) {
423 if (it != members.begin())
426 document_ += yamlCompatibilityEnabled_ ?
": " :
":";
427 writeValue(value[name]);
441 addChildValues_ =
false;
442 indentString_.clear();
443 writeCommentBeforeValue(root);
445 writeCommentAfterValueOnSameLine(root);
450 void StyledWriter::writeValue(
const Value& value) {
451 switch (value.
type()) {
479 writeArrayValue(value);
486 writeWithIndent(
"{");
488 auto it = members.begin();
491 const Value& childValue = value[name];
492 writeCommentBeforeValue(childValue);
495 writeValue(childValue);
496 if (++it == members.end()) {
497 writeCommentAfterValueOnSameLine(childValue);
501 writeCommentAfterValueOnSameLine(childValue);
504 writeWithIndent(
"}");
510 void StyledWriter::writeArrayValue(
const Value& value) {
511 size_t size = value.
size();
515 bool isArrayMultiLine = isMultilineArray(value);
516 if (isArrayMultiLine) {
517 writeWithIndent(
"[");
519 bool hasChildValue = !childValues_.empty();
522 const Value& childValue = value[index];
523 writeCommentBeforeValue(childValue);
525 writeWithIndent(childValues_[index]);
528 writeValue(childValue);
530 if (++index == size) {
531 writeCommentAfterValueOnSameLine(childValue);
535 writeCommentAfterValueOnSameLine(childValue);
538 writeWithIndent(
"]");
541 assert(childValues_.size() == size);
543 for (
size_t index = 0; index < size; ++index) {
546 document_ += childValues_[index];
553 bool StyledWriter::isMultilineArray(
const Value& value) {
555 bool isMultiLine = size * 3 >= rightMargin_;
556 childValues_.clear();
557 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
558 const Value& childValue = value[index];
560 !childValue.
empty());
564 childValues_.reserve(size);
565 addChildValues_ =
true;
567 for (
ArrayIndex index = 0; index < size; ++index) {
568 if (hasCommentForValue(value[index])) {
571 writeValue(value[index]);
572 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
574 addChildValues_ =
false;
575 isMultiLine = isMultiLine || lineLength >= rightMargin_;
580 void StyledWriter::pushValue(
const String& value) {
582 childValues_.push_back(value);
587 void StyledWriter::writeIndent() {
588 if (!document_.empty()) {
589 char last = document_[document_.length() - 1];
595 document_ += indentString_;
598 void StyledWriter::writeWithIndent(
const String& value) {
603 void StyledWriter::indent() { indentString_ +=
String(indentSize_,
' '); }
605 void StyledWriter::unindent() {
606 assert(indentString_.size() >= indentSize_);
607 indentString_.resize(indentString_.size() - indentSize_);
610 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
617 String::const_iterator iter = comment.begin();
618 while (iter != comment.end()) {
620 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
629 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
640 bool StyledWriter::hasCommentForValue(
const Value& value) {
650 : document_(nullptr), indentation_(
std::move(indentation)),
651 addChildValues_(), indented_(false) {}
655 addChildValues_ =
false;
656 indentString_.clear();
658 writeCommentBeforeValue(root);
663 writeCommentAfterValueOnSameLine(root);
668 void StyledStreamWriter::writeValue(
const Value& value) {
669 switch (value.
type()) {
697 writeArrayValue(value);
704 writeWithIndent(
"{");
706 auto it = members.begin();
709 const Value& childValue = value[name];
710 writeCommentBeforeValue(childValue);
713 writeValue(childValue);
714 if (++it == members.end()) {
715 writeCommentAfterValueOnSameLine(childValue);
719 writeCommentAfterValueOnSameLine(childValue);
722 writeWithIndent(
"}");
728 void StyledStreamWriter::writeArrayValue(
const Value& value) {
729 unsigned size = value.
size();
733 bool isArrayMultiLine = isMultilineArray(value);
734 if (isArrayMultiLine) {
735 writeWithIndent(
"[");
737 bool hasChildValue = !childValues_.empty();
740 const Value& childValue = value[index];
741 writeCommentBeforeValue(childValue);
743 writeWithIndent(childValues_[index]);
748 writeValue(childValue);
751 if (++index == size) {
752 writeCommentAfterValueOnSameLine(childValue);
756 writeCommentAfterValueOnSameLine(childValue);
759 writeWithIndent(
"]");
762 assert(childValues_.size() == size);
764 for (
unsigned index = 0; index < size; ++index) {
767 *document_ << childValues_[index];
774 bool StyledStreamWriter::isMultilineArray(
const Value& value) {
776 bool isMultiLine = size * 3 >= rightMargin_;
777 childValues_.clear();
778 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
779 const Value& childValue = value[index];
781 !childValue.
empty());
785 childValues_.reserve(size);
786 addChildValues_ =
true;
788 for (
ArrayIndex index = 0; index < size; ++index) {
789 if (hasCommentForValue(value[index])) {
792 writeValue(value[index]);
793 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
795 addChildValues_ =
false;
796 isMultiLine = isMultiLine || lineLength >= rightMargin_;
801 void StyledStreamWriter::pushValue(
const String& value) {
803 childValues_.push_back(value);
808 void StyledStreamWriter::writeIndent() {
813 *document_ <<
'\n' << indentString_;
816 void StyledStreamWriter::writeWithIndent(
const String& value) {
823 void StyledStreamWriter::indent() { indentString_ += indentation_; }
825 void StyledStreamWriter::unindent() {
826 assert(indentString_.size() >= indentation_.size());
827 indentString_.resize(indentString_.size() - indentation_.size());
830 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
837 String::const_iterator iter = comment.begin();
838 while (iter != comment.end()) {
840 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
842 *document_ << indentString_;
848 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
859 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
869 struct CommentStyle {
879 BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs,
881 String endingLineFeedSymbol,
bool useSpecialFloats,
882 bool emitUTF8,
unsigned int precision,
887 void writeValue(
Value const& value);
888 void writeArrayValue(
Value const& value);
889 bool isMultilineArray(
Value const& value);
890 void pushValue(
String const& value);
892 void writeWithIndent(
String const& value);
895 void writeCommentBeforeValue(
Value const& root);
896 void writeCommentAfterValueOnSameLine(
Value const& root);
897 static bool hasCommentForValue(
const Value& value);
899 using ChildValues = std::vector<String>;
901 ChildValues childValues_;
903 unsigned int rightMargin_;
905 CommentStyle::Enum cs_;
908 String endingLineFeedSymbol_;
909 bool addChildValues_ : 1;
911 bool useSpecialFloats_ : 1;
913 unsigned int precision_;
916 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
917 String indentation, CommentStyle::Enum cs,
String colonSymbol,
918 String nullSymbol,
String endingLineFeedSymbol,
bool useSpecialFloats,
919 bool emitUTF8,
unsigned int precision,
PrecisionType precisionType)
920 : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
921 colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
922 endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
923 addChildValues_(
false), indented_(
false),
924 useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
925 precision_(precision), precisionType_(precisionType) {}
926 int BuiltStyledStreamWriter::write(
Value const& root,
OStream* sout) {
928 addChildValues_ =
false;
930 indentString_.clear();
931 writeCommentBeforeValue(root);
936 writeCommentAfterValueOnSameLine(root);
937 *sout_ << endingLineFeedSymbol_;
941 void BuiltStyledStreamWriter::writeValue(
Value const& value) {
942 switch (value.
type()) {
944 pushValue(nullSymbol_);
972 writeArrayValue(value);
979 writeWithIndent(
"{");
981 auto it = members.begin();
984 Value const& childValue = value[name];
985 writeCommentBeforeValue(childValue);
988 *sout_ << colonSymbol_;
989 writeValue(childValue);
990 if (++it == members.end()) {
991 writeCommentAfterValueOnSameLine(childValue);
995 writeCommentAfterValueOnSameLine(childValue);
998 writeWithIndent(
"}");
1004 void BuiltStyledStreamWriter::writeArrayValue(
Value const& value) {
1005 unsigned size = value.
size();
1009 bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
1011 writeWithIndent(
"[");
1013 bool hasChildValue = !childValues_.empty();
1016 Value const& childValue = value[index];
1017 writeCommentBeforeValue(childValue);
1019 writeWithIndent(childValues_[index]);
1024 writeValue(childValue);
1027 if (++index == size) {
1028 writeCommentAfterValueOnSameLine(childValue);
1032 writeCommentAfterValueOnSameLine(childValue);
1035 writeWithIndent(
"]");
1038 assert(childValues_.size() == size);
1040 if (!indentation_.empty())
1042 for (
unsigned index = 0; index < size; ++index) {
1044 *sout_ << ((!indentation_.empty()) ?
", " :
",");
1045 *sout_ << childValues_[index];
1047 if (!indentation_.empty())
1054 bool BuiltStyledStreamWriter::isMultilineArray(
Value const& value) {
1056 bool isMultiLine = size * 3 >= rightMargin_;
1057 childValues_.clear();
1058 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
1059 Value const& childValue = value[index];
1061 !childValue.
empty());
1065 childValues_.reserve(size);
1066 addChildValues_ =
true;
1068 for (
ArrayIndex index = 0; index < size; ++index) {
1069 if (hasCommentForValue(value[index])) {
1072 writeValue(value[index]);
1073 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
1075 addChildValues_ =
false;
1076 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1081 void BuiltStyledStreamWriter::pushValue(
String const& value) {
1082 if (addChildValues_)
1083 childValues_.push_back(value);
1088 void BuiltStyledStreamWriter::writeIndent() {
1094 if (!indentation_.empty()) {
1096 *sout_ <<
'\n' << indentString_;
1100 void BuiltStyledStreamWriter::writeWithIndent(
String const& value) {
1107 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1109 void BuiltStyledStreamWriter::unindent() {
1110 assert(indentString_.size() >= indentation_.size());
1111 indentString_.resize(indentString_.size() - indentation_.size());
1114 void BuiltStyledStreamWriter::writeCommentBeforeValue(
Value const& root) {
1115 if (cs_ == CommentStyle::None)
1123 String::const_iterator iter = comment.begin();
1124 while (iter != comment.end()) {
1126 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
1128 *sout_ << indentString_;
1134 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
1135 Value const& root) {
1136 if (cs_ == CommentStyle::None)
1148 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1163 const String indentation = settings_[
"indentation"].asString();
1164 const String cs_str = settings_[
"commentStyle"].asString();
1165 const String pt_str = settings_[
"precisionType"].asString();
1166 const bool eyc = settings_[
"enableYAMLCompatibility"].asBool();
1167 const bool dnp = settings_[
"dropNullPlaceholders"].asBool();
1168 const bool usf = settings_[
"useSpecialFloats"].asBool();
1169 const bool emitUTF8 = settings_[
"emitUTF8"].asBool();
1170 unsigned int pre = settings_[
"precision"].asUInt();
1171 CommentStyle::Enum cs = CommentStyle::All;
1172 if (cs_str ==
"All") {
1173 cs = CommentStyle::All;
1174 }
else if (cs_str ==
"None") {
1175 cs = CommentStyle::None;
1177 throwRuntimeError(
"commentStyle must be 'All' or 'None'");
1180 if (pt_str ==
"significant") {
1182 }
else if (pt_str ==
"decimal") {
1185 throwRuntimeError(
"precisionType must be 'significant' or 'decimal'");
1187 String colonSymbol =
" : ";
1190 }
else if (indentation.empty()) {
1193 String nullSymbol =
"null";
1199 String endingLineFeedSymbol;
1200 return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
1201 endingLineFeedSymbol, usf, emitUTF8, pre,
1206 static const auto& valid_keys = *
new std::set<String>{
1209 "enableYAMLCompatibility",
1210 "dropNullPlaceholders",
1216 for (
auto si = settings_.begin(); si != settings_.end(); ++si) {
1217 auto key = si.name();
1218 if (valid_keys.count(key))
1221 (*invalid)[key] = *si;
1225 return invalid ? invalid->
empty() :
true;
1229 return settings_[key];
1234 (*settings)[
"commentStyle"] =
"All";
1235 (*settings)[
"indentation"] =
"\t";
1236 (*settings)[
"enableYAMLCompatibility"] =
false;
1237 (*settings)[
"dropNullPlaceholders"] =
false;
1238 (*settings)[
"useSpecialFloats"] =
false;
1239 (*settings)[
"emitUTF8"] =
false;
1240 (*settings)[
"precision"] = 17;
1241 (*settings)[
"precisionType"] =
"significant";
1248 writer->write(root, &sout);
1255 writer->write(root, &sout);
A simple abstract factory.
void omitEndingLineFeed()
bool validate(Json::Value *invalid) const
std::auto_ptr< StreamWriter > StreamWriterPtr
static constexpr LargestInt minLargestInt
Minimum signed integer value that can be stored in a Json::Value.
static void uintToString(LargestUInt value, char *¤t)
Converts an unsigned integer to string.
static void setDefaults(Json::Value *settings)
Called by ctor, but you can use this to reset settings_.
PrecisionType
Type of precision for formatting of real values.
LargestUInt asLargestUInt() const
static void appendRaw(String &result, unsigned ch)
array value (ordered list)
String valueToString(Int value)
bool empty() const
Return true if empty array, empty object, or null; otherwise, false.
Members getMemberNames() const
Return a list of the member names.
object value (collection of name/value pairs).
bool getString(char const **begin, char const **end) const
Get raw char* of string-value.
StreamWriter * newStreamWriter() const override
void enableYAMLCompatibility()
Iter fixNumericLocale(Iter begin, Iter end)
Change ',' to '.
char[uintToStringBufferSize] UIntToStringBuffer
static String valueToQuotedStringN(const char *value, size_t length, bool emitUTF8=false)
std::basic_ostringstream< String::value_type, String::traits_type, String::allocator_type > OStringStream
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::vector< String > Members
ArrayIndex size() const
Number of values in array or object.
String write(const Value &root) override
Serialize a Value in JSON format.
LargestInt asLargestInt() const
String writeString(StreamWriter::Factory const &factory, Value const &root)
Write into stringstream, then return string, for convenience.
~StreamWriterBuilder() override
static void appendHex(String &result, unsigned ch)
JSON (JavaScript Object Notation).
void write(OStream &out, const Value &root)
Serialize a Value in JSON format.
Value & operator[](const String &key)
A simple way to update a specific setting.
we set max number of digits after "." in string
String getComment(CommentPlacement placement) const
Include delimiters and embedded newlines.
static constexpr LargestInt maxLargestInt
Maximum signed integer value that can be stored in a Json::Value.
StyledStreamWriter(String indentation="\)
static unsigned int utf8ToCodepoint(const char *&s, const char *e)
a comment on the line after a value (only make sense for
bool hasComment(CommentPlacement placement) const
String valueToQuotedString(const char *value)
we set max number of significant digits in string
void dropNullPlaceholders()
Drop the "null" string from the writer's output for nullValues.
String write(const Value &root) override
static String toHex16Bit(unsigned int x)
static bool doesAnyCharRequireEscaping(char const *s, size_t n)
a comment placed on the line before a value
a comment just after a value on the same line
Build a StreamWriter implementation.
std::basic_string< char, std::char_traits< char >, Allocator< char > > String
OStream & operator<<(OStream &, const Value &root)
Output using the StyledStreamWriter.
virtual StreamWriter * newStreamWriter() const =0
Allocate a CharReader via operator new().