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);
164 if (buffer.find(
'.') == buffer.npos && buffer.find(
'e') == buffer.npos) {
173 return valueToString(value,
false, precision, precisionType);
181 return std::any_of(s, s + n, [](
unsigned char c) {
182 return c ==
'\\' || c ==
'"' || c < 0x20 || c > 0x7F;
187 const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
189 unsigned int firstByte =
static_cast<unsigned char>(*s);
191 if (firstByte < 0x80)
194 if (firstByte < 0xE0) {
196 return REPLACEMENT_CHARACTER;
198 unsigned int calculated =
199 ((firstByte & 0x1F) << 6) | (
static_cast<unsigned int>(s[1]) & 0x3F);
202 return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
205 if (firstByte < 0xF0) {
207 return REPLACEMENT_CHARACTER;
209 unsigned int calculated = ((firstByte & 0x0F) << 12) |
210 ((
static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
211 (static_cast<unsigned int>(s[2]) & 0x3F);
215 if (calculated >= 0xD800 && calculated <= 0xDFFF)
216 return REPLACEMENT_CHARACTER;
218 return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
221 if (firstByte < 0xF8) {
223 return REPLACEMENT_CHARACTER;
225 unsigned int calculated = ((firstByte & 0x07) << 18) |
226 ((
static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
227 ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
228 (
static_cast<unsigned int>(s[3]) & 0x3F);
231 return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
234 return REPLACEMENT_CHARACTER;
237 static const char hex2[] =
"000102030405060708090a0b0c0d0e0f" 238 "101112131415161718191a1b1c1d1e1f" 239 "202122232425262728292a2b2c2d2e2f" 240 "303132333435363738393a3b3c3d3e3f" 241 "404142434445464748494a4b4c4d4e4f" 242 "505152535455565758595a5b5c5d5e5f" 243 "606162636465666768696a6b6c6d6e6f" 244 "707172737475767778797a7b7c7d7e7f" 245 "808182838485868788898a8b8c8d8e8f" 246 "909192939495969798999a9b9c9d9e9f" 247 "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 248 "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" 249 "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" 250 "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" 251 "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" 252 "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
255 const unsigned int hi = (x >> 8) & 0xff;
256 const unsigned int lo = x & 0xff;
258 result[0] = hex2[2 * hi];
259 result[1] = hex2[2 * hi + 1];
260 result[2] = hex2[2 * lo];
261 result[3] = hex2[2 * lo + 1];
266 result +=
static_cast<char>(ch);
274 bool emitUTF8 =
false) {
275 if (value ==
nullptr)
279 return String(
"\"") + value +
"\"";
283 String::size_type maxsize = length * 2 + 3;
285 result.reserve(maxsize);
287 char const* end = value + length;
288 for (
const char* c = value; c != end; ++c) {
321 unsigned codepoint =
static_cast<unsigned char>(*c);
322 if (codepoint < 0x20) {
329 if (codepoint < 0x20) {
331 }
else if (codepoint < 0x80) {
333 }
else if (codepoint < 0x10000) {
338 codepoint -= 0x10000;
339 appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
340 appendHex(result, 0xdc00 + (codepoint & 0x3ff));
356 Writer::~Writer() =
default;
361 FastWriter::FastWriter()
365 void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ =
true; }
367 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ =
true; }
369 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ =
true; }
374 if (!omitEndingLineFeed_)
379 void FastWriter::writeValue(
const Value& value) {
380 switch (value.
type()) {
382 if (!dropNullPlaceholders_)
409 for (
ArrayIndex index = 0; index < size; ++index) {
412 writeValue(value[index]);
419 for (
auto it = members.begin(); it != members.end(); ++it) {
421 if (it != members.begin())
424 static_cast<unsigned>(name.length()));
425 document_ += yamlCompatibilityEnabled_ ?
": " :
":";
426 writeValue(value[name]);
436 StyledWriter::StyledWriter() =
default;
440 addChildValues_ =
false;
441 indentString_.clear();
442 writeCommentBeforeValue(root);
444 writeCommentAfterValueOnSameLine(root);
449 void StyledWriter::writeValue(
const Value& value) {
450 switch (value.
type()) {
478 writeArrayValue(value);
485 writeWithIndent(
"{");
487 auto it = members.begin();
490 const Value& childValue = value[name];
491 writeCommentBeforeValue(childValue);
494 writeValue(childValue);
495 if (++it == members.end()) {
496 writeCommentAfterValueOnSameLine(childValue);
500 writeCommentAfterValueOnSameLine(childValue);
503 writeWithIndent(
"}");
509 void StyledWriter::writeArrayValue(
const Value& value) {
510 unsigned size = value.
size();
514 bool isArrayMultiLine = isMultilineArray(value);
515 if (isArrayMultiLine) {
516 writeWithIndent(
"[");
518 bool hasChildValue = !childValues_.empty();
521 const Value& childValue = value[index];
522 writeCommentBeforeValue(childValue);
524 writeWithIndent(childValues_[index]);
527 writeValue(childValue);
529 if (++index == size) {
530 writeCommentAfterValueOnSameLine(childValue);
534 writeCommentAfterValueOnSameLine(childValue);
537 writeWithIndent(
"]");
540 assert(childValues_.size() == size);
542 for (
unsigned index = 0; index < size; ++index) {
545 document_ += childValues_[index];
552 bool StyledWriter::isMultilineArray(
const Value& value) {
554 bool isMultiLine = size * 3 >= rightMargin_;
555 childValues_.clear();
556 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
557 const Value& childValue = value[index];
559 !childValue.
empty());
563 childValues_.reserve(size);
564 addChildValues_ =
true;
566 for (
ArrayIndex index = 0; index < size; ++index) {
567 if (hasCommentForValue(value[index])) {
570 writeValue(value[index]);
571 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
573 addChildValues_ =
false;
574 isMultiLine = isMultiLine || lineLength >= rightMargin_;
579 void StyledWriter::pushValue(
const String& value) {
581 childValues_.push_back(value);
586 void StyledWriter::writeIndent() {
587 if (!document_.empty()) {
588 char last = document_[document_.length() - 1];
594 document_ += indentString_;
597 void StyledWriter::writeWithIndent(
const String& value) {
602 void StyledWriter::indent() { indentString_ +=
String(indentSize_,
' '); }
604 void StyledWriter::unindent() {
605 assert(indentString_.size() >= indentSize_);
606 indentString_.resize(indentString_.size() - indentSize_);
609 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
616 String::const_iterator iter = comment.begin();
617 while (iter != comment.end()) {
619 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
628 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
639 bool StyledWriter::hasCommentForValue(
const Value& value) {
648 StyledStreamWriter::StyledStreamWriter(
String indentation)
649 : document_(
nullptr), indentation_(std::move(indentation)),
650 addChildValues_(), indented_(
false) {}
652 void StyledStreamWriter::write(
OStream& out,
const Value& root) {
654 addChildValues_ =
false;
655 indentString_.clear();
657 writeCommentBeforeValue(root);
662 writeCommentAfterValueOnSameLine(root);
667 void StyledStreamWriter::writeValue(
const Value& value) {
668 switch (value.
type()) {
696 writeArrayValue(value);
703 writeWithIndent(
"{");
705 auto it = members.begin();
708 const Value& childValue = value[name];
709 writeCommentBeforeValue(childValue);
712 writeValue(childValue);
713 if (++it == members.end()) {
714 writeCommentAfterValueOnSameLine(childValue);
718 writeCommentAfterValueOnSameLine(childValue);
721 writeWithIndent(
"}");
727 void StyledStreamWriter::writeArrayValue(
const Value& value) {
728 unsigned size = value.
size();
732 bool isArrayMultiLine = isMultilineArray(value);
733 if (isArrayMultiLine) {
734 writeWithIndent(
"[");
736 bool hasChildValue = !childValues_.empty();
739 const Value& childValue = value[index];
740 writeCommentBeforeValue(childValue);
742 writeWithIndent(childValues_[index]);
747 writeValue(childValue);
750 if (++index == size) {
751 writeCommentAfterValueOnSameLine(childValue);
755 writeCommentAfterValueOnSameLine(childValue);
758 writeWithIndent(
"]");
761 assert(childValues_.size() == size);
763 for (
unsigned index = 0; index < size; ++index) {
766 *document_ << childValues_[index];
773 bool StyledStreamWriter::isMultilineArray(
const Value& value) {
775 bool isMultiLine = size * 3 >= rightMargin_;
776 childValues_.clear();
777 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
778 const Value& childValue = value[index];
780 !childValue.
empty());
784 childValues_.reserve(size);
785 addChildValues_ =
true;
787 for (
ArrayIndex index = 0; index < size; ++index) {
788 if (hasCommentForValue(value[index])) {
791 writeValue(value[index]);
792 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
794 addChildValues_ =
false;
795 isMultiLine = isMultiLine || lineLength >= rightMargin_;
800 void StyledStreamWriter::pushValue(
const String& value) {
802 childValues_.push_back(value);
807 void StyledStreamWriter::writeIndent() {
812 *document_ <<
'\n' << indentString_;
815 void StyledStreamWriter::writeWithIndent(
const String& value) {
822 void StyledStreamWriter::indent() { indentString_ += indentation_; }
824 void StyledStreamWriter::unindent() {
825 assert(indentString_.size() >= indentation_.size());
826 indentString_.resize(indentString_.size() - indentation_.size());
829 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
836 String::const_iterator iter = comment.begin();
837 while (iter != comment.end()) {
839 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
841 *document_ << indentString_;
847 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
858 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
868 struct CommentStyle {
878 BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs,
880 String endingLineFeedSymbol,
bool useSpecialFloats,
881 bool emitUTF8,
unsigned int precision,
886 void writeValue(
Value const& value);
887 void writeArrayValue(
Value const& value);
888 bool isMultilineArray(
Value const& value);
889 void pushValue(
String const& value);
891 void writeWithIndent(
String const& value);
894 void writeCommentBeforeValue(
Value const& root);
895 void writeCommentAfterValueOnSameLine(
Value const& root);
896 static bool hasCommentForValue(
const Value& value);
898 using ChildValues = std::vector<String>;
900 ChildValues childValues_;
902 unsigned int rightMargin_;
904 CommentStyle::Enum cs_;
907 String endingLineFeedSymbol_;
908 bool addChildValues_ : 1;
910 bool useSpecialFloats_ : 1;
912 unsigned int precision_;
915 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
916 String indentation, CommentStyle::Enum cs,
String colonSymbol,
917 String nullSymbol,
String endingLineFeedSymbol,
bool useSpecialFloats,
918 bool emitUTF8,
unsigned int precision,
PrecisionType precisionType)
919 : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
920 colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
921 endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
922 addChildValues_(
false), indented_(
false),
923 useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
924 precision_(precision), precisionType_(precisionType) {}
925 int BuiltStyledStreamWriter::write(
Value const& root,
OStream* sout) {
927 addChildValues_ =
false;
929 indentString_.clear();
930 writeCommentBeforeValue(root);
935 writeCommentAfterValueOnSameLine(root);
936 *sout_ << endingLineFeedSymbol_;
940 void BuiltStyledStreamWriter::writeValue(
Value const& value) {
941 switch (value.
type()) {
943 pushValue(nullSymbol_);
971 writeArrayValue(value);
978 writeWithIndent(
"{");
980 auto it = members.begin();
983 Value const& childValue = value[name];
984 writeCommentBeforeValue(childValue);
986 name.data(),
static_cast<unsigned>(name.length()), emitUTF8_));
987 *sout_ << colonSymbol_;
988 writeValue(childValue);
989 if (++it == members.end()) {
990 writeCommentAfterValueOnSameLine(childValue);
994 writeCommentAfterValueOnSameLine(childValue);
997 writeWithIndent(
"}");
1003 void BuiltStyledStreamWriter::writeArrayValue(
Value const& value) {
1004 unsigned size = value.
size();
1008 bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
1010 writeWithIndent(
"[");
1012 bool hasChildValue = !childValues_.empty();
1015 Value const& childValue = value[index];
1016 writeCommentBeforeValue(childValue);
1018 writeWithIndent(childValues_[index]);
1023 writeValue(childValue);
1026 if (++index == size) {
1027 writeCommentAfterValueOnSameLine(childValue);
1031 writeCommentAfterValueOnSameLine(childValue);
1034 writeWithIndent(
"]");
1037 assert(childValues_.size() == size);
1039 if (!indentation_.empty())
1041 for (
unsigned index = 0; index < size; ++index) {
1043 *sout_ << ((!indentation_.empty()) ?
", " :
",");
1044 *sout_ << childValues_[index];
1046 if (!indentation_.empty())
1053 bool BuiltStyledStreamWriter::isMultilineArray(
Value const& value) {
1055 bool isMultiLine = size * 3 >= rightMargin_;
1056 childValues_.clear();
1057 for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
1058 Value const& childValue = value[index];
1060 !childValue.
empty());
1064 childValues_.reserve(size);
1065 addChildValues_ =
true;
1067 for (
ArrayIndex index = 0; index < size; ++index) {
1068 if (hasCommentForValue(value[index])) {
1071 writeValue(value[index]);
1072 lineLength +=
static_cast<ArrayIndex>(childValues_[index].length());
1074 addChildValues_ =
false;
1075 isMultiLine = isMultiLine || lineLength >= rightMargin_;
1080 void BuiltStyledStreamWriter::pushValue(
String const& value) {
1081 if (addChildValues_)
1082 childValues_.push_back(value);
1087 void BuiltStyledStreamWriter::writeIndent() {
1093 if (!indentation_.empty()) {
1095 *sout_ <<
'\n' << indentString_;
1099 void BuiltStyledStreamWriter::writeWithIndent(
String const& value) {
1106 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
1108 void BuiltStyledStreamWriter::unindent() {
1109 assert(indentString_.size() >= indentation_.size());
1110 indentString_.resize(indentString_.size() - indentation_.size());
1113 void BuiltStyledStreamWriter::writeCommentBeforeValue(
Value const& root) {
1114 if (cs_ == CommentStyle::None)
1122 String::const_iterator iter = comment.begin();
1123 while (iter != comment.end()) {
1125 if (*iter ==
'\n' && ((iter + 1) != comment.end() && *(iter + 1) ==
'/'))
1127 *sout_ << indentString_;
1133 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
1134 Value const& root) {
1135 if (cs_ == CommentStyle::None)
1147 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
1162 const String indentation = settings_[
"indentation"].asString();
1163 const String cs_str = settings_[
"commentStyle"].asString();
1164 const String pt_str = settings_[
"precisionType"].asString();
1165 const bool eyc = settings_[
"enableYAMLCompatibility"].asBool();
1166 const bool dnp = settings_[
"dropNullPlaceholders"].asBool();
1167 const bool usf = settings_[
"useSpecialFloats"].asBool();
1168 const bool emitUTF8 = settings_[
"emitUTF8"].asBool();
1169 unsigned int pre = settings_[
"precision"].asUInt();
1170 CommentStyle::Enum cs = CommentStyle::All;
1171 if (cs_str ==
"All") {
1172 cs = CommentStyle::All;
1173 }
else if (cs_str ==
"None") {
1174 cs = CommentStyle::None;
1176 throwRuntimeError(
"commentStyle must be 'All' or 'None'");
1179 if (pt_str ==
"significant") {
1181 }
else if (pt_str ==
"decimal") {
1184 throwRuntimeError(
"precisionType must be 'significant' or 'decimal'");
1186 String colonSymbol =
" : ";
1189 }
else if (indentation.empty()) {
1192 String nullSymbol =
"null";
1198 String endingLineFeedSymbol;
1199 return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
1200 endingLineFeedSymbol, usf, emitUTF8, pre,
1205 static const auto& valid_keys = *
new std::set<String>{
1208 "enableYAMLCompatibility",
1209 "dropNullPlaceholders",
1215 for (
auto si = settings_.begin(); si != settings_.end(); ++si) {
1216 auto key = si.name();
1217 if (valid_keys.count(key))
1220 (*invalid)[std::move(key)] = *si;
1224 return invalid ? invalid->
empty() :
true;
1228 return settings_[key];
1233 (*settings)[
"commentStyle"] =
"All";
1234 (*settings)[
"indentation"] =
"\t";
1235 (*settings)[
"enableYAMLCompatibility"] =
false;
1236 (*settings)[
"dropNullPlaceholders"] =
false;
1237 (*settings)[
"useSpecialFloats"] =
false;
1238 (*settings)[
"emitUTF8"] =
false;
1239 (*settings)[
"precision"] = 17;
1240 (*settings)[
"precisionType"] =
"significant";
1247 writer->write(root, &sout);
1254 writer->write(root, &sout);
A simple abstract factory.
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
Iter fixZerosInTheEnd(Iter begin, Iter end)
Return iterator that would be the new end of the range [begin,end), if we were to delete zeros in the...
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
Iter fixNumericLocale(Iter begin, Iter end)
Change ',' to '.
char[uintToStringBufferSize] UIntToStringBuffer
std::basic_ostringstream< String::value_type, String::traits_type, String::allocator_type > OStringStream
static String valueToQuotedStringN(const char *value, unsigned length, bool emitUTF8=false)
std::vector< String > Members
ArrayIndex size() const
Number of values in array or object.
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).
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.
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
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().