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) 
  126                      bool useSpecialFloats,
 
  127                      unsigned int precision,
 
  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) {
 
  172                      unsigned int precision,
 
  174   return valueToString(value, 
false, precision, precisionType);
 
  182   char const* 
const end = s + n;
 
  183   for (
char const* cur = s; cur < end; ++cur) {
 
  184     if (*cur == 
'\\' || *cur == 
'\"' || *cur < 
' ' ||
 
  185         static_cast<unsigned char>(*cur) < 0x80)
 
  192   const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
 
  194   unsigned int firstByte = static_cast<unsigned char>(*s);
 
  196   if (firstByte < 0x80)
 
  199   if (firstByte < 0xE0) {
 
  201       return REPLACEMENT_CHARACTER;
 
  203     unsigned int calculated =
 
  204         ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
 
  207     return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
 
  210   if (firstByte < 0xF0) {
 
  212       return REPLACEMENT_CHARACTER;
 
  214     unsigned int calculated = ((firstByte & 0x0F) << 12) |
 
  215                               ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
 
  216                               (static_cast<unsigned int>(s[2]) & 0x3F);
 
  220     if (calculated >= 0xD800 && calculated <= 0xDFFF)
 
  221       return REPLACEMENT_CHARACTER;
 
  223     return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
 
  226   if (firstByte < 0xF8) {
 
  228       return REPLACEMENT_CHARACTER;
 
  230     unsigned int calculated = ((firstByte & 0x07) << 18) |
 
  231                               ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
 
  232                               ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
 
  233                               (static_cast<unsigned int>(s[3]) & 0x3F);
 
  236     return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
 
  239   return REPLACEMENT_CHARACTER;
 
  242 static const char hex2[] = 
"000102030405060708090a0b0c0d0e0f" 
  243                            "101112131415161718191a1b1c1d1e1f" 
  244                            "202122232425262728292a2b2c2d2e2f" 
  245                            "303132333435363738393a3b3c3d3e3f" 
  246                            "404142434445464748494a4b4c4d4e4f" 
  247                            "505152535455565758595a5b5c5d5e5f" 
  248                            "606162636465666768696a6b6c6d6e6f" 
  249                            "707172737475767778797a7b7c7d7e7f" 
  250                            "808182838485868788898a8b8c8d8e8f" 
  251                            "909192939495969798999a9b9c9d9e9f" 
  252                            "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf" 
  253                            "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf" 
  254                            "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf" 
  255                            "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf" 
  256                            "e0e1e2e3e4e5e6e7e8e9eaebecedeeef" 
  257                            "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
 
  260   const unsigned int hi = (x >> 8) & 0xff;
 
  261   const unsigned int lo = x & 0xff;
 
  263   result[0] = 
hex2[2 * hi];
 
  264   result[1] = 
hex2[2 * hi + 1];
 
  265   result[2] = 
hex2[2 * lo];
 
  266   result[3] = 
hex2[2 * lo + 1];
 
  271   if (value == 
nullptr)
 
  275     return String(
"\"") + value + 
"\"";
 
  279   String::size_type maxsize = length * 2 + 3; 
 
  281   result.reserve(maxsize); 
 
  283   char const* end = value + length;
 
  284   for (
const char* c = value; c != end; ++c) {
 
  319       if (cp < 0x80 && cp >= 0x20)
 
  320         result += static_cast<char>(cp);
 
  321       else if (cp < 0x10000) { 
 
  345 Writer::~Writer() = 
default;
 
  350 FastWriter::FastWriter()
 
  354 void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = 
true; }
 
  356 void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = 
true; }
 
  358 void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = 
true; }
 
  360 String FastWriter::write(
const Value& root) {
 
  363   if (!omitEndingLineFeed_)
 
  368 void FastWriter::writeValue(
const Value& value) {
 
  369   switch (value.type()) {
 
  371     if (!dropNullPlaceholders_)
 
  387     bool ok = value.getString(&str, &end);
 
  398     for (
ArrayIndex index = 0; index < size; ++index) {
 
  401       writeValue(value[index]);
 
  408     for (
auto it = members.begin(); it != members.end(); ++it) {
 
  410       if (it != members.begin())
 
  413                                         static_cast<unsigned>(name.length()));
 
  414       document_ += yamlCompatibilityEnabled_ ? 
": " : 
":";
 
  415       writeValue(value[name]);
 
  425 StyledWriter::StyledWriter() = 
default;
 
  427 String StyledWriter::write(
const Value& root) {
 
  429   addChildValues_ = 
false;
 
  430   indentString_.clear();
 
  431   writeCommentBeforeValue(root);
 
  433   writeCommentAfterValueOnSameLine(root);
 
  438 void StyledWriter::writeValue(
const Value& value) {
 
  439   switch (value.type()) {
 
  456     bool ok = value.getString(&str, &end);
 
  467     writeArrayValue(value);
 
  474       writeWithIndent(
"{");
 
  476       auto it = members.begin();
 
  479         const Value& childValue = value[name];
 
  480         writeCommentBeforeValue(childValue);
 
  483         writeValue(childValue);
 
  484         if (++it == members.end()) {
 
  485           writeCommentAfterValueOnSameLine(childValue);
 
  489         writeCommentAfterValueOnSameLine(childValue);
 
  492       writeWithIndent(
"}");
 
  498 void StyledWriter::writeArrayValue(
const Value& value) {
 
  499   unsigned size = value.size();
 
  503     bool isArrayMultiLine = isMultilineArray(value);
 
  504     if (isArrayMultiLine) {
 
  505       writeWithIndent(
"[");
 
  507       bool hasChildValue = !childValues_.empty();
 
  510         const Value& childValue = value[index];
 
  511         writeCommentBeforeValue(childValue);
 
  513           writeWithIndent(childValues_[index]);
 
  516           writeValue(childValue);
 
  518         if (++index == size) {
 
  519           writeCommentAfterValueOnSameLine(childValue);
 
  523         writeCommentAfterValueOnSameLine(childValue);
 
  526       writeWithIndent(
"]");
 
  529       assert(childValues_.size() == size);
 
  531       for (
unsigned index = 0; index < size; ++index) {
 
  534         document_ += childValues_[index];
 
  541 bool StyledWriter::isMultilineArray(
const Value& value) {
 
  543   bool isMultiLine = size * 3 >= rightMargin_;
 
  544   childValues_.clear();
 
  545   for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
 
  546     const Value& childValue = value[index];
 
  547     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
  548                    !childValue.empty());
 
  552     childValues_.reserve(size);
 
  553     addChildValues_ = 
true;
 
  555     for (
ArrayIndex index = 0; index < size; ++index) {
 
  556       if (hasCommentForValue(value[index])) {
 
  559       writeValue(value[index]);
 
  560       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
 
  562     addChildValues_ = 
false;
 
  563     isMultiLine = isMultiLine || lineLength >= rightMargin_;
 
  568 void StyledWriter::pushValue(
const String& value) {
 
  570     childValues_.push_back(value);
 
  575 void StyledWriter::writeIndent() {
 
  576   if (!document_.empty()) {
 
  577     char last = document_[document_.length() - 1];
 
  583   document_ += indentString_;
 
  586 void StyledWriter::writeWithIndent(
const String& value) {
 
  591 void StyledWriter::indent() { indentString_ += 
String(indentSize_, 
' '); }
 
  593 void StyledWriter::unindent() {
 
  594   assert(indentString_.size() >= indentSize_);
 
  595   indentString_.resize(indentString_.size() - indentSize_);
 
  598 void StyledWriter::writeCommentBeforeValue(
const Value& root) {
 
  605   String::const_iterator iter = comment.begin();
 
  606   while (iter != comment.end()) {
 
  608     if (*iter == 
'\n' && ((iter + 1) != comment.end() && *(iter + 1) == 
'/'))
 
  617 void StyledWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
 
  628 bool StyledWriter::hasCommentForValue(
const Value& value) {
 
  637 StyledStreamWriter::StyledStreamWriter(
String indentation)
 
  638     : document_(nullptr), indentation_(std::move(indentation)),
 
  639       addChildValues_(), indented_(false) {}
 
  641 void StyledStreamWriter::write(
OStream& out, 
const Value& root) {
 
  643   addChildValues_ = 
false;
 
  644   indentString_.clear();
 
  646   writeCommentBeforeValue(root);
 
  651   writeCommentAfterValueOnSameLine(root);
 
  656 void StyledStreamWriter::writeValue(
const Value& value) {
 
  657   switch (value.type()) {
 
  674     bool ok = value.getString(&str, &end);
 
  685     writeArrayValue(value);
 
  688     Value::Members members(value.getMemberNames());
 
  692       writeWithIndent(
"{");
 
  694       auto it = members.begin();
 
  697         const Value& childValue = value[name];
 
  698         writeCommentBeforeValue(childValue);
 
  701         writeValue(childValue);
 
  702         if (++it == members.end()) {
 
  703           writeCommentAfterValueOnSameLine(childValue);
 
  707         writeCommentAfterValueOnSameLine(childValue);
 
  710       writeWithIndent(
"}");
 
  716 void StyledStreamWriter::writeArrayValue(
const Value& value) {
 
  717   unsigned size = value.size();
 
  721     bool isArrayMultiLine = isMultilineArray(value);
 
  722     if (isArrayMultiLine) {
 
  723       writeWithIndent(
"[");
 
  725       bool hasChildValue = !childValues_.empty();
 
  728         const Value& childValue = value[index];
 
  729         writeCommentBeforeValue(childValue);
 
  731           writeWithIndent(childValues_[index]);
 
  736           writeValue(childValue);
 
  739         if (++index == size) {
 
  740           writeCommentAfterValueOnSameLine(childValue);
 
  744         writeCommentAfterValueOnSameLine(childValue);
 
  747       writeWithIndent(
"]");
 
  750       assert(childValues_.size() == size);
 
  752       for (
unsigned index = 0; index < size; ++index) {
 
  755         *document_ << childValues_[index];
 
  762 bool StyledStreamWriter::isMultilineArray(
const Value& value) {
 
  764   bool isMultiLine = size * 3 >= rightMargin_;
 
  765   childValues_.clear();
 
  766   for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
 
  767     const Value& childValue = value[index];
 
  768     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
  769                    !childValue.empty());
 
  773     childValues_.reserve(size);
 
  774     addChildValues_ = 
true;
 
  776     for (
ArrayIndex index = 0; index < size; ++index) {
 
  777       if (hasCommentForValue(value[index])) {
 
  780       writeValue(value[index]);
 
  781       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
 
  783     addChildValues_ = 
false;
 
  784     isMultiLine = isMultiLine || lineLength >= rightMargin_;
 
  789 void StyledStreamWriter::pushValue(
const String& value) {
 
  791     childValues_.push_back(value);
 
  796 void StyledStreamWriter::writeIndent() {
 
  801   *document_ << 
'\n' << indentString_;
 
  804 void StyledStreamWriter::writeWithIndent(
const String& value) {
 
  811 void StyledStreamWriter::indent() { indentString_ += indentation_; }
 
  813 void StyledStreamWriter::unindent() {
 
  814   assert(indentString_.size() >= indentation_.size());
 
  815   indentString_.resize(indentString_.size() - indentation_.size());
 
  818 void StyledStreamWriter::writeCommentBeforeValue(
const Value& root) {
 
  825   String::const_iterator iter = comment.begin();
 
  826   while (iter != comment.end()) {
 
  828     if (*iter == 
'\n' && ((iter + 1) != comment.end() && *(iter + 1) == 
'/'))
 
  830       *document_ << indentString_;
 
  836 void StyledStreamWriter::writeCommentAfterValueOnSameLine(
const Value& root) {
 
  847 bool StyledStreamWriter::hasCommentForValue(
const Value& value) {
 
  857 struct CommentStyle {
 
  866 struct BuiltStyledStreamWriter : 
public StreamWriter {
 
  867   BuiltStyledStreamWriter(
String indentation,
 
  868                           CommentStyle::Enum cs,
 
  871                           String endingLineFeedSymbol,
 
  872                           bool useSpecialFloats,
 
  873                           unsigned int precision,
 
  875   int write(Value 
const& root, 
OStream* sout) 
override;
 
  878   void writeValue(Value 
const& value);
 
  879   void writeArrayValue(Value 
const& value);
 
  880   bool isMultilineArray(Value 
const& value);
 
  881   void pushValue(
String const& value);
 
  883   void writeWithIndent(
String const& value);
 
  886   void writeCommentBeforeValue(Value 
const& root);
 
  887   void writeCommentAfterValueOnSameLine(Value 
const& root);
 
  888   static bool hasCommentForValue(
const Value& value);
 
  890   typedef std::vector<String> ChildValues;
 
  892   ChildValues childValues_;
 
  894   unsigned int rightMargin_;
 
  896   CommentStyle::Enum cs_;
 
  899   String endingLineFeedSymbol_;
 
  900   bool addChildValues_ : 1;
 
  902   bool useSpecialFloats_ : 1;
 
  903   unsigned int precision_;
 
  906 BuiltStyledStreamWriter::BuiltStyledStreamWriter(
String indentation,
 
  907                                                  CommentStyle::Enum cs,
 
  910                                                  String endingLineFeedSymbol,
 
  911                                                  bool useSpecialFloats,
 
  912                                                  unsigned int precision,
 
  914     : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
 
  915       colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
 
  916       endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
 
  917       addChildValues_(false), indented_(false),
 
  918       useSpecialFloats_(useSpecialFloats), precision_(precision),
 
  919       precisionType_(precisionType) {}
 
  920 int BuiltStyledStreamWriter::write(Value 
const& root, 
OStream* sout) {
 
  922   addChildValues_ = 
false;
 
  924   indentString_.clear();
 
  925   writeCommentBeforeValue(root);
 
  930   writeCommentAfterValueOnSameLine(root);
 
  931   *sout_ << endingLineFeedSymbol_;
 
  935 void BuiltStyledStreamWriter::writeValue(Value 
const& value) {
 
  936   switch (value.type()) {
 
  938     pushValue(nullSymbol_);
 
  947     pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_,
 
  954     bool ok = value.getString(&str, &end);
 
  965     writeArrayValue(value);
 
  968     Value::Members members(value.getMemberNames());
 
  972       writeWithIndent(
"{");
 
  974       auto it = members.begin();
 
  977         Value 
const& childValue = value[name];
 
  978         writeCommentBeforeValue(childValue);
 
  980             name.data(), static_cast<unsigned>(name.length())));
 
  981         *sout_ << colonSymbol_;
 
  982         writeValue(childValue);
 
  983         if (++it == members.end()) {
 
  984           writeCommentAfterValueOnSameLine(childValue);
 
  988         writeCommentAfterValueOnSameLine(childValue);
 
  991       writeWithIndent(
"}");
 
  997 void BuiltStyledStreamWriter::writeArrayValue(Value 
const& value) {
 
  998   unsigned size = value.size();
 
 1002     bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
 
 1004       writeWithIndent(
"[");
 
 1006       bool hasChildValue = !childValues_.empty();
 
 1009         Value 
const& childValue = value[index];
 
 1010         writeCommentBeforeValue(childValue);
 
 1012           writeWithIndent(childValues_[index]);
 
 1017           writeValue(childValue);
 
 1020         if (++index == size) {
 
 1021           writeCommentAfterValueOnSameLine(childValue);
 
 1025         writeCommentAfterValueOnSameLine(childValue);
 
 1028       writeWithIndent(
"]");
 
 1031       assert(childValues_.size() == size);
 
 1033       if (!indentation_.empty())
 
 1035       for (
unsigned index = 0; index < size; ++index) {
 
 1037           *sout_ << ((!indentation_.empty()) ? 
", " : 
",");
 
 1038         *sout_ << childValues_[index];
 
 1040       if (!indentation_.empty())
 
 1047 bool BuiltStyledStreamWriter::isMultilineArray(Value 
const& value) {
 
 1049   bool isMultiLine = size * 3 >= rightMargin_;
 
 1050   childValues_.clear();
 
 1051   for (
ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
 
 1052     Value 
const& childValue = value[index];
 
 1053     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
 1054                    !childValue.empty());
 
 1058     childValues_.reserve(size);
 
 1059     addChildValues_ = 
true;
 
 1061     for (
ArrayIndex index = 0; index < size; ++index) {
 
 1062       if (hasCommentForValue(value[index])) {
 
 1065       writeValue(value[index]);
 
 1066       lineLength += static_cast<ArrayIndex>(childValues_[index].length());
 
 1068     addChildValues_ = 
false;
 
 1069     isMultiLine = isMultiLine || lineLength >= rightMargin_;
 
 1074 void BuiltStyledStreamWriter::pushValue(
String const& value) {
 
 1075   if (addChildValues_)
 
 1076     childValues_.push_back(value);
 
 1081 void BuiltStyledStreamWriter::writeIndent() {
 
 1087   if (!indentation_.empty()) {
 
 1089     *sout_ << 
'\n' << indentString_;
 
 1093 void BuiltStyledStreamWriter::writeWithIndent(
String const& value) {
 
 1100 void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
 
 1102 void BuiltStyledStreamWriter::unindent() {
 
 1103   assert(indentString_.size() >= indentation_.size());
 
 1104   indentString_.resize(indentString_.size() - indentation_.size());
 
 1107 void BuiltStyledStreamWriter::writeCommentBeforeValue(Value 
const& root) {
 
 1108   if (cs_ == CommentStyle::None)
 
 1116   String::const_iterator iter = comment.begin();
 
 1117   while (iter != comment.end()) {
 
 1119     if (*iter == 
'\n' && ((iter + 1) != comment.end() && *(iter + 1) == 
'/'))
 
 1121       *sout_ << indentString_;
 
 1127 void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
 
 1128     Value 
const& root) {
 
 1129   if (cs_ == CommentStyle::None)
 
 1141 bool BuiltStyledStreamWriter::hasCommentForValue(
const Value& value) {
 
 1150 StreamWriter::StreamWriter() : sout_(nullptr) {}
 
 1163   CommentStyle::Enum cs = CommentStyle::All;
 
 1164   if (cs_str == 
"All") {
 
 1165     cs = CommentStyle::All;
 
 1166   } 
else if (cs_str == 
"None") {
 
 1167     cs = CommentStyle::None;
 
 1172   if (pt_str == 
"significant") {
 
 1174   } 
else if (pt_str == 
"decimal") {
 
 1179   String colonSymbol = 
" : ";
 
 1182   } 
else if (indentation.empty()) {
 
 1185   String nullSymbol = 
"null";
 
 1191   String endingLineFeedSymbol;
 
 1192   return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
 
 1193                                      endingLineFeedSymbol, usf, pre,
 
 1197   valid_keys->clear();
 
 1198   valid_keys->insert(
"indentation");
 
 1199   valid_keys->insert(
"commentStyle");
 
 1200   valid_keys->insert(
"enableYAMLCompatibility");
 
 1201   valid_keys->insert(
"dropNullPlaceholders");
 
 1202   valid_keys->insert(
"useSpecialFloats");
 
 1203   valid_keys->insert(
"precision");
 
 1204   valid_keys->insert(
"precisionType");
 
 1209     invalid = &my_invalid; 
 
 1211   std::set<String> valid_keys;
 
 1214   size_t n = keys.size();
 
 1215   for (
size_t i = 0; i < n; ++i) {
 
 1216     String const& key = keys[i];
 
 1217     if (valid_keys.find(key) == valid_keys.end()) {
 
 1229   (*settings)[
"commentStyle"] = 
"All";
 
 1230   (*settings)[
"indentation"] = 
"\t";
 
 1231   (*settings)[
"enableYAMLCompatibility"] = 
false;
 
 1232   (*settings)[
"dropNullPlaceholders"] = 
false;
 
 1233   (*settings)[
"useSpecialFloats"] = 
false;
 
 1234   (*settings)[
"precision"] = 17;
 
 1235   (*settings)[
"precisionType"] = 
"significant";
 
 1242   writer->write(root, &sout);
 
 1249   writer->write(root, &sout);