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 == 
'"' || !std::isprint(c);
 
  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; }
 
  371 String FastWriter::write(
const Value& root) {
 
  374   if (!omitEndingLineFeed_)
 
  379 void FastWriter::writeValue(
const Value& value) {
 
  380   switch (value.type()) {
 
  382     if (!dropNullPlaceholders_)
 
  398     bool ok = value.getString(&str, &end);
 
  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;
 
  438 String StyledWriter::write(
const Value& root) {
 
  440   addChildValues_ = 
false;
 
  441   indentString_.clear();
 
  442   writeCommentBeforeValue(root);
 
  444   writeCommentAfterValueOnSameLine(root);
 
  449 void StyledWriter::writeValue(
const Value& value) {
 
  450   switch (value.type()) {
 
  467     bool ok = value.getString(&str, &end);
 
  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];
 
  558     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
  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()) {
 
  685     bool ok = value.getString(&str, &end);
 
  696     writeArrayValue(value);
 
  699     Value::Members members(value.getMemberNames());
 
  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];
 
  779     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
  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 {
 
  877 struct BuiltStyledStreamWriter : 
public StreamWriter {
 
  878   BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs,
 
  880                           String endingLineFeedSymbol, 
bool useSpecialFloats,
 
  881                           bool emitUTF8, 
unsigned int precision,
 
  883   int write(Value 
const& root, 
OStream* sout) 
override;
 
  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_);
 
  952     pushValue(
valueToString(value.asDouble(), useSpecialFloats_, precision_,
 
  959     bool ok = value.getString(&str, &end);
 
  971     writeArrayValue(value);
 
  974     Value::Members members(value.getMemberNames());
 
  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];
 
 1059     isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
 
 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) {
 
 1156 StreamWriter::StreamWriter() : sout_(nullptr) {}
 
 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",
 
 1216     auto key = si.name();
 
 1217     if (valid_keys.count(key))
 
 1220       (*invalid)[std::move(key)] = *si;
 
 1224   return invalid ? invalid->
empty() : 
true;
 
 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);