summaryrefslogtreecommitdiff
path: root/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Utilities/cmjsoncpp/src/lib_json/json_writer.cpp')
-rw-r--r--Utilities/cmjsoncpp/src/lib_json/json_writer.cpp822
1 files changed, 411 insertions, 411 deletions
diff --git a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
index fc86505983..8bf02dbdbc 100644
--- a/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
+++ b/Utilities/cmjsoncpp/src/lib_json/json_writer.cpp
@@ -4,106 +4,81 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
-#include <json/writer.h>
#include "json_tool.h"
+#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
+#include <algorithm>
+#include <cassert>
+#include <cctype>
+#include <cstring>
#include <iomanip>
#include <memory>
+#include <set>
#include <sstream>
#include <utility>
-#include <set>
-#include <cassert>
-#include <cstring>
+
+#if __cplusplus >= 201103L
+#include <cmath>
#include <cstdio>
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
-#include <float.h>
-#define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) //Solaris
-#if !defined(isfinite)
-#include <ieeefp.h>
-#define isfinite finite
+#if !defined(isnan)
+#define isnan std::isnan
#endif
-#elif defined(_AIX)
+
#if !defined(isfinite)
-#include <math.h>
-#define isfinite finite
-#endif
-#elif defined(__hpux)
-#if !defined(isfinite) && !defined(__GNUC__)
-#if defined(__ia64) && !defined(finite)
-#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _IsFinite(x)))
-#else
-#include <math.h>
-#define isfinite finite
-#endif
+#define isfinite std::isfinite
#endif
+
#else
#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
-#endif
+#include <cstdio>
#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#if !defined(__MINGW32__) && !defined(__CYGWIN__)
-#define snprintf std::snprintf
-#endif
+#if !defined(isnan)
+#include <float.h>
+#define isnan _isnan
#endif
-#if defined(__BORLANDC__)
+#if !defined(isfinite)
#include <float.h>
#define isfinite _finite
-#define snprintf _snprintf
#endif
-// Solaris
-#if defined(__sun)
-# include <ieeefp.h>
-# if !defined(isfinite)
-# define isfinite finite
-# endif
-#endif
+#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
+#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
+#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
+
+#endif //_MSC_VER
-// AIX
-#if defined(_AIX)
-# if !defined(isfinite)
-# define isfinite finite
-# endif
+#if defined(__sun) && defined(__SVR4) // Solaris
+#if !defined(isfinite)
+#include <ieeefp.h>
+#define isfinite finite
+#endif
#endif
-// HP-UX
#if defined(__hpux)
-# if !defined(isfinite)
-# if defined(__ia64) && !defined(finite) && !defined(__GNUC__)
-# define isfinite(x) ((sizeof(x) == sizeof(float) ? \
- _Isfinitef(x) : _Isfinite(x)))
-# else
-# include <math.h>
-# define isfinite finite
-# endif
-# endif
+#if !defined(isfinite)
+#if defined(__ia64) && !defined(finite)
+#define isfinite(x) \
+ ((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
+#endif
+#endif
+#endif
+
+#if !defined(isnan)
+// IEEE standard states that NaN values will not compare to themselves
+#define isnan(x) (x != x)
#endif
-// Ancient glibc
-#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 2
-# if !defined(isfinite)
-# define isfinite __finite
-# endif
+#if !defined(__APPLE__)
+#if !defined(isfinite)
+#define isfinite finite
+#endif
+#endif
#endif
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
+#if defined(_MSC_VER)
// Disable warning about strdup being deprecated.
#pragma warning(disable : 4996)
#endif
@@ -111,30 +86,12 @@
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else
-typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
+using StreamWriterPtr = std::auto_ptr<StreamWriter>;
#endif
-static bool containsControlCharacter(const char* str) {
- while (*str) {
- if (isControlCharacter(*(str++)))
- return true;
- }
- return false;
-}
-
-static bool containsControlCharacter0(const char* str, unsigned len) {
- char const* end = str + len;
- while (end != str) {
- if (isControlCharacter(*str) || 0==*str)
- return true;
- ++str;
- }
- return false;
-}
-
-JSONCPP_STRING valueToString(LargestInt value) {
+String valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
if (value == Value::minLargestInt) {
@@ -150,7 +107,7 @@ JSONCPP_STRING valueToString(LargestInt value) {
return current;
}
-JSONCPP_STRING valueToString(LargestUInt value) {
+String valueToString(LargestUInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
uintToString(value, current);
@@ -160,147 +117,171 @@ JSONCPP_STRING valueToString(LargestUInt value) {
#if defined(JSON_HAS_INT64)
-JSONCPP_STRING valueToString(Int value) {
- return valueToString(LargestInt(value));
-}
+String valueToString(Int value) { return valueToString(LargestInt(value)); }
-JSONCPP_STRING valueToString(UInt value) {
- return valueToString(LargestUInt(value));
-}
+String valueToString(UInt value) { return valueToString(LargestUInt(value)); }
#endif // # if defined(JSON_HAS_INT64)
namespace {
-JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
- // Allocate a buffer that is more than large enough to store the 16 digits of
- // precision requested below.
- char buffer[36];
- int len = -1;
-
- char formatString[15];
- snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
-
+String valueToString(double value, bool useSpecialFloats,
+ unsigned int precision, PrecisionType precisionType) {
// Print into the buffer. We need not request the alternative representation
- // that always has a decimal point because JSON doesn't distingish the
+ // that always has a decimal point because JSON doesn't distinguish the
// concepts of reals and integers.
- if (isfinite(value)) {
- len = snprintf(buffer, sizeof(buffer), formatString, value);
- fixNumericLocale(buffer, buffer + len);
+ if (!isfinite(value)) {
+ static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
+ {"null", "-1e+9999", "1e+9999"}};
+ return reps[useSpecialFloats ? 0 : 1]
+ [isnan(value) ? 0 : (value < 0) ? 1 : 2];
+ }
- // try to ensure we preserve the fact that this was given to us as a double on input
- if (!strchr(buffer, '.') && !strchr(buffer, 'e')) {
- strcat(buffer, ".0");
+ String buffer(size_t(36), '\0');
+ while (true) {
+ int len = jsoncpp_snprintf(
+ &*buffer.begin(), buffer.size(),
+ (precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
+ precision, value);
+ assert(len >= 0);
+ auto wouldPrint = static_cast<size_t>(len);
+ if (wouldPrint >= buffer.size()) {
+ buffer.resize(wouldPrint + 1);
+ continue;
}
+ buffer.resize(wouldPrint);
+ break;
+ }
- } else {
- // IEEE standard states that NaN values will not compare to themselves
- if (value != value) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
- } else if (value < 0) {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
- } else {
- len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
- }
+ buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
+
+ // strip the zero padding from the right
+ if (precisionType == PrecisionType::decimalPlaces) {
+ buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
+ }
+
+ // try to ensure we preserve the fact that this was given to us as a double on
+ // input
+ if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
+ buffer += ".0";
}
- assert(len >= 0);
return buffer;
}
+} // namespace
+
+String valueToString(double value, unsigned int precision,
+ PrecisionType precisionType) {
+ return valueToString(value, false, precision, precisionType);
}
-JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
+String valueToString(bool value) { return value ? "true" : "false"; }
-JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
+static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
+ assert(s || !n);
-JSONCPP_STRING valueToQuotedString(const char* value) {
- if (value == NULL)
- return "";
- // Not sure how to handle unicode...
- if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
- !containsControlCharacter(value))
- return JSONCPP_STRING("\"") + value + "\"";
- // We have to walk value and escape any special characters.
- // Appending to JSONCPP_STRING is not efficient, but this should be rare.
- // (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- strlen(value) * 2 + 3; // allescaped+quotes+NULL
- JSONCPP_STRING result;
- result.reserve(maxsize); // to avoid lots of mallocs
- result += "\"";
- for (const char* c = value; *c != 0; ++c) {
- switch (*c) {
- case '\"':
- result += "\\\"";
- break;
- case '\\':
- result += "\\\\";
- break;
- case '\b':
- result += "\\b";
- break;
- case '\f':
- result += "\\f";
- break;
- case '\n':
- result += "\\n";
- break;
- case '\r':
- result += "\\r";
- break;
- case '\t':
- result += "\\t";
- break;
- // case '/':
- // Even though \/ is considered a legal escape in JSON, a bare
- // slash is also legal, so I see no reason to escape it.
- // (I hope I am not misunderstanding something.
- // blep notes: actually escaping \/ may be useful in javascript to avoid </
- // sequence.
- // Should add a flag to allow this compatibility mode and prevent this
- // sequence from occurring.
- default:
- if (isControlCharacter(*c)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
- } else {
- result += *c;
- }
- break;
- }
+ return std::any_of(s, s + n, [](unsigned char c) {
+ return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
+ });
+}
+
+static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
+ const unsigned int REPLACEMENT_CHARACTER = 0xFFFD;
+
+ unsigned int firstByte = static_cast<unsigned char>(*s);
+
+ if (firstByte < 0x80)
+ return firstByte;
+
+ if (firstByte < 0xE0) {
+ if (e - s < 2)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated =
+ ((firstByte & 0x1F) << 6) | (static_cast<unsigned int>(s[1]) & 0x3F);
+ s += 1;
+ // oversized encoded characters are invalid
+ return calculated < 0x80 ? REPLACEMENT_CHARACTER : calculated;
}
- result += "\"";
+
+ if (firstByte < 0xF0) {
+ if (e - s < 3)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x0F) << 12) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[2]) & 0x3F);
+ s += 2;
+ // surrogates aren't valid codepoints itself
+ // shouldn't be UTF-8 encoded
+ if (calculated >= 0xD800 && calculated <= 0xDFFF)
+ return REPLACEMENT_CHARACTER;
+ // oversized encoded characters are invalid
+ return calculated < 0x800 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ if (firstByte < 0xF8) {
+ if (e - s < 4)
+ return REPLACEMENT_CHARACTER;
+
+ unsigned int calculated = ((firstByte & 0x07) << 18) |
+ ((static_cast<unsigned int>(s[1]) & 0x3F) << 12) |
+ ((static_cast<unsigned int>(s[2]) & 0x3F) << 6) |
+ (static_cast<unsigned int>(s[3]) & 0x3F);
+ s += 3;
+ // oversized encoded characters are invalid
+ return calculated < 0x10000 ? REPLACEMENT_CHARACTER : calculated;
+ }
+
+ return REPLACEMENT_CHARACTER;
+}
+
+static const char hex2[] = "000102030405060708090a0b0c0d0e0f"
+ "101112131415161718191a1b1c1d1e1f"
+ "202122232425262728292a2b2c2d2e2f"
+ "303132333435363738393a3b3c3d3e3f"
+ "404142434445464748494a4b4c4d4e4f"
+ "505152535455565758595a5b5c5d5e5f"
+ "606162636465666768696a6b6c6d6e6f"
+ "707172737475767778797a7b7c7d7e7f"
+ "808182838485868788898a8b8c8d8e8f"
+ "909192939495969798999a9b9c9d9e9f"
+ "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+ "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+ "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+ "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+ "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+ "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
+
+static String toHex16Bit(unsigned int x) {
+ const unsigned int hi = (x >> 8) & 0xff;
+ const unsigned int lo = x & 0xff;
+ String result(4, ' ');
+ result[0] = hex2[2 * hi];
+ result[1] = hex2[2 * hi + 1];
+ result[2] = hex2[2 * lo];
+ result[3] = hex2[2 * lo + 1];
return result;
}
-// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n) {
- assert((s || !n) && accept);
+static void appendRaw(String& result, unsigned ch) {
+ result += static_cast<char>(ch);
+}
- char const* const end = s + n;
- for (char const* cur = s; cur < end; ++cur) {
- int const c = *cur;
- for (char const* a = accept; *a; ++a) {
- if (*a == c) {
- return cur;
- }
- }
- }
- return NULL;
+static void appendHex(String& result, unsigned ch) {
+ result.append("\\u").append(toHex16Bit(ch));
}
-static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
- if (value == NULL)
+
+static String valueToQuotedStringN(const char* value, unsigned length,
+ bool emitUTF8 = false) {
+ if (value == nullptr)
return "";
- // Not sure how to handle unicode...
- if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
- !containsControlCharacter0(value, length))
- return JSONCPP_STRING("\"") + value + "\"";
+
+ if (!doesAnyCharRequireEscaping(value, length))
+ return String("\"") + value + "\"";
// We have to walk value and escape any special characters.
- // Appending to JSONCPP_STRING is not efficient, but this should be rare.
+ // Appending to String is not efficient, but this should be rare.
// (Note: forward slashes are *not* rare, but I am not escaping them.)
- JSONCPP_STRING::size_type maxsize =
- length * 2 + 3; // allescaped+quotes+NULL
- JSONCPP_STRING result;
+ String::size_type maxsize = length * 2 + 3; // allescaped+quotes+NULL
+ String result;
result.reserve(maxsize); // to avoid lots of mallocs
result += "\"";
char const* end = value + length;
@@ -335,44 +316,63 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
// sequence.
// Should add a flag to allow this compatibility mode and prevent this
// sequence from occurring.
- default:
- if ((isControlCharacter(*c)) || (*c == 0)) {
- JSONCPP_OSTRINGSTREAM oss;
- oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
- << std::setw(4) << static_cast<int>(*c);
- result += oss.str();
+ default: {
+ if (emitUTF8) {
+ unsigned codepoint = static_cast<unsigned char>(*c);
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else {
+ appendRaw(result, codepoint);
+ }
} else {
- result += *c;
+ unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
+ if (codepoint < 0x20) {
+ appendHex(result, codepoint);
+ } else if (codepoint < 0x80) {
+ appendRaw(result, codepoint);
+ } else if (codepoint < 0x10000) {
+ // Basic Multilingual Plane
+ appendHex(result, codepoint);
+ } else {
+ // Extended Unicode. Encode 20 bits as a surrogate pair.
+ codepoint -= 0x10000;
+ appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
+ appendHex(result, 0xdc00 + (codepoint & 0x3ff));
+ }
}
- break;
+ } break;
}
}
result += "\"";
return result;
}
+String valueToQuotedString(const char* value) {
+ return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
+}
+
// Class Writer
// //////////////////////////////////////////////////////////////////
-Writer::~Writer() {}
+Writer::~Writer() = default;
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
- omitEndingLineFeed_(false) {}
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+ = default;
+
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
-JSONCPP_STRING FastWriter::write(const Value& root) {
+String FastWriter::write(const Value& root) {
document_.clear();
writeValue(root);
if (!omitEndingLineFeed_)
- document_ += "\n";
+ document_ += '\n';
return document_;
}
@@ -391,13 +391,13 @@ void FastWriter::writeValue(const Value& value) {
case realValue:
document_ += valueToString(value.asDouble());
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
+ if (ok)
+ document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
break;
}
case booleanValue:
@@ -416,13 +416,13 @@ void FastWriter::writeValue(const Value& value) {
case objectValue: {
Value::Members members(value.getMemberNames());
document_ += '{';
- for (Value::Members::iterator it = members.begin(); it != members.end();
- ++it) {
- const JSONCPP_STRING& name = *it;
+ for (auto it = members.begin(); it != members.end(); ++it) {
+ const String& name = *it;
if (it != members.begin())
document_ += ',';
- document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ document_ += valueToQuotedStringN(name.data(),
+ static_cast<unsigned>(name.length()));
+ document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
document_ += '}';
@@ -433,17 +433,16 @@ void FastWriter::writeValue(const Value& value) {
// Class StyledWriter
// //////////////////////////////////////////////////////////////////
-StyledWriter::StyledWriter()
- : rightMargin_(74), indentSize_(3), addChildValues_() {}
+StyledWriter::StyledWriter() = default;
-JSONCPP_STRING StyledWriter::write(const Value& root) {
+String StyledWriter::write(const Value& root) {
document_.clear();
addChildValues_ = false;
indentString_.clear();
writeCommentBeforeValue(root);
writeValue(root);
writeCommentAfterValueOnSameLine(root);
- document_ += "\n";
+ document_ += '\n';
return document_;
}
@@ -461,14 +460,15 @@ void StyledWriter::writeValue(const Value& value) {
case realValue:
pushValue(valueToString(value.asDouble()));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -484,9 +484,9 @@ void StyledWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- const JSONCPP_STRING& name = *it;
+ const String& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -511,7 +511,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -549,14 +549,14 @@ void StyledWriter::writeArrayValue(const Value& value) {
}
}
-bool StyledWriter::isMultineArray(const Value& value) {
+bool StyledWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -576,7 +576,7 @@ bool StyledWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledWriter::pushValue(const JSONCPP_STRING& value) {
+void StyledWriter::pushValue(const String& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -594,12 +594,12 @@ void StyledWriter::writeIndent() {
document_ += indentString_;
}
-void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
+void StyledWriter::writeWithIndent(const String& value) {
writeIndent();
document_ += value;
}
-void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
+void StyledWriter::indent() { indentString_ += String(indentSize_, ' '); }
void StyledWriter::unindent() {
assert(indentString_.size() >= indentSize_);
@@ -610,20 +610,19 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- document_ += "\n";
+ document_ += '\n';
writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
document_ += *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
writeIndent();
++iter;
}
// Comments are stripped of trailing newlines, so add one here
- document_ += "\n";
+ document_ += '\n';
}
void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
@@ -631,9 +630,9 @@ void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
document_ += " " + root.getComment(commentAfterOnSameLine);
if (root.hasComment(commentAfter)) {
- document_ += "\n";
+ document_ += '\n';
document_ += root.getComment(commentAfter);
- document_ += "\n";
+ document_ += '\n';
}
}
@@ -646,22 +645,23 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
// Class StyledStreamWriter
// //////////////////////////////////////////////////////////////////
-StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
- : document_(NULL), rightMargin_(74), indentation_(indentation),
- addChildValues_() {}
+StyledStreamWriter::StyledStreamWriter(String indentation)
+ : document_(nullptr), indentation_(std::move(indentation)),
+ addChildValues_(), indented_(false) {}
-void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
+void StyledStreamWriter::write(OStream& out, const Value& root) {
document_ = &out;
addChildValues_ = false;
indentString_.clear();
indented_ = true;
writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*document_ << "\n";
- document_ = NULL; // Forget the stream, for safety.
+ document_ = nullptr; // Forget the stream, for safety.
}
void StyledStreamWriter::writeValue(const Value& value) {
@@ -678,14 +678,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
case realValue:
pushValue(valueToString(value.asDouble()));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -701,9 +702,9 @@ void StyledStreamWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- const JSONCPP_STRING& name = *it;
+ const String& name = *it;
const Value& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedString(name.c_str()));
@@ -728,7 +729,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -740,7 +741,8 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (hasChildValue)
writeWithIndent(childValues_[index]);
else {
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(childValue);
indented_ = false;
@@ -768,14 +770,14 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
}
}
-bool StyledStreamWriter::isMultineArray(const Value& value) {
+bool StyledStreamWriter::isMultilineArray(const Value& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -795,7 +797,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) {
return isMultiLine;
}
-void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
+void StyledStreamWriter::pushValue(const String& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -810,8 +812,9 @@ void StyledStreamWriter::writeIndent() {
*document_ << '\n' << indentString_;
}
-void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
- if (!indented_) writeIndent();
+void StyledStreamWriter::writeWithIndent(const String& value) {
+ if (!indented_)
+ writeIndent();
*document_ << value;
indented_ = false;
}
@@ -827,13 +830,13 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*document_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would include newline
*document_ << indentString_;
++iter;
@@ -865,84 +868,73 @@ bool StyledStreamWriter::hasCommentForValue(const Value& value) {
struct CommentStyle {
/// Decide whether to write comments.
enum Enum {
- None, ///< Drop all comments.
- Most, ///< Recover odd behavior of previous versions (not implemented yet).
- All ///< Keep all comments.
+ None, ///< Drop all comments.
+ Most, ///< Recover odd behavior of previous versions (not implemented yet).
+ All ///< Keep all comments.
};
};
-struct BuiltStyledStreamWriter : public StreamWriter
-{
- BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision);
- int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
+struct BuiltStyledStreamWriter : public StreamWriter {
+ BuiltStyledStreamWriter(String indentation, CommentStyle::Enum cs,
+ String colonSymbol, String nullSymbol,
+ String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision,
+ PrecisionType precisionType);
+ int write(Value const& root, OStream* sout) override;
+
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
- bool isMultineArray(Value const& value);
- void pushValue(JSONCPP_STRING const& value);
+ bool isMultilineArray(Value const& value);
+ void pushValue(String const& value);
void writeIndent();
- void writeWithIndent(JSONCPP_STRING const& value);
+ void writeWithIndent(String const& value);
void indent();
void unindent();
void writeCommentBeforeValue(Value const& root);
void writeCommentAfterValueOnSameLine(Value const& root);
static bool hasCommentForValue(const Value& value);
- typedef std::vector<JSONCPP_STRING> ChildValues;
+ using ChildValues = std::vector<String>;
ChildValues childValues_;
- JSONCPP_STRING indentString_;
+ String indentString_;
unsigned int rightMargin_;
- JSONCPP_STRING indentation_;
+ String indentation_;
CommentStyle::Enum cs_;
- JSONCPP_STRING colonSymbol_;
- JSONCPP_STRING nullSymbol_;
- JSONCPP_STRING endingLineFeedSymbol_;
+ String colonSymbol_;
+ String nullSymbol_;
+ String endingLineFeedSymbol_;
bool addChildValues_ : 1;
bool indented_ : 1;
bool useSpecialFloats_ : 1;
+ bool emitUTF8_ : 1;
unsigned int precision_;
+ PrecisionType precisionType_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
- JSONCPP_STRING const& indentation,
- CommentStyle::Enum cs,
- JSONCPP_STRING const& colonSymbol,
- JSONCPP_STRING const& nullSymbol,
- JSONCPP_STRING const& endingLineFeedSymbol,
- bool useSpecialFloats,
- unsigned int precision)
- : rightMargin_(74)
- , indentation_(indentation)
- , cs_(cs)
- , colonSymbol_(colonSymbol)
- , nullSymbol_(nullSymbol)
- , endingLineFeedSymbol_(endingLineFeedSymbol)
- , addChildValues_(false)
- , indented_(false)
- , useSpecialFloats_(useSpecialFloats)
- , precision_(precision)
-{
-}
-int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
-{
+ String indentation, CommentStyle::Enum cs, String colonSymbol,
+ String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
+ bool emitUTF8, unsigned int precision, PrecisionType precisionType)
+ : rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
+ colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
+ endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
+ addChildValues_(false), indented_(false),
+ useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
+ precision_(precision), precisionType_(precisionType) {}
+int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
sout_ = sout;
addChildValues_ = false;
indented_ = true;
indentString_.clear();
writeCommentBeforeValue(root);
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*sout_ << endingLineFeedSymbol_;
- sout_ = NULL;
+ sout_ = nullptr;
return 0;
}
void BuiltStyledStreamWriter::writeValue(Value const& value) {
@@ -957,16 +949,19 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
pushValue(valueToString(value.asLargestUInt()));
break;
case realValue:
- pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
+ pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_,
+ precisionType_));
break;
- case stringValue:
- {
+ case stringValue: {
// Is NULL is possible for value.string_? No.
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
- if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
- else pushValue("");
+ if (ok)
+ pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
+ emitUTF8_));
+ else
+ pushValue("");
break;
}
case booleanValue:
@@ -982,12 +977,13 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
else {
writeWithIndent("{");
indent();
- Value::Members::iterator it = members.begin();
+ auto it = members.begin();
for (;;) {
- JSONCPP_STRING const& name = *it;
+ String const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
- writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
+ writeWithIndent(valueToQuotedStringN(
+ name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -1009,7 +1005,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (size == 0)
pushValue("[]");
else {
- bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
+ bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
if (isMultiLine) {
writeWithIndent("[");
indent();
@@ -1021,7 +1017,8 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (hasChildValue)
writeWithIndent(childValues_[index]);
else {
- if (!indented_) writeIndent();
+ if (!indented_)
+ writeIndent();
indented_ = true;
writeValue(childValue);
indented_ = false;
@@ -1039,26 +1036,28 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
{
assert(childValues_.size() == size);
*sout_ << "[";
- if (!indentation_.empty()) *sout_ << " ";
+ if (!indentation_.empty())
+ *sout_ << " ";
for (unsigned index = 0; index < size; ++index) {
if (index > 0)
*sout_ << ((!indentation_.empty()) ? ", " : ",");
*sout_ << childValues_[index];
}
- if (!indentation_.empty()) *sout_ << " ";
+ if (!indentation_.empty())
+ *sout_ << " ";
*sout_ << "]";
}
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
- childValue.size() > 0);
+ !childValue.empty());
}
if (!isMultiLine) // check if line length > max line length
{
@@ -1078,7 +1077,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
return isMultiLine;
}
-void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
+void BuiltStyledStreamWriter::pushValue(String const& value) {
if (addChildValues_)
childValues_.push_back(value);
else
@@ -1097,8 +1096,9 @@ void BuiltStyledStreamWriter::writeIndent() {
}
}
-void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
- if (!indented_) writeIndent();
+void BuiltStyledStreamWriter::writeWithIndent(String const& value) {
+ if (!indented_)
+ writeIndent();
*sout_ << value;
indented_ = false;
}
@@ -1111,17 +1111,18 @@ void BuiltStyledStreamWriter::unindent() {
}
void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+ if (cs_ == CommentStyle::None)
+ return;
if (!root.hasComment(commentBefore))
return;
- if (!indented_) writeIndent();
- const JSONCPP_STRING& comment = root.getComment(commentBefore);
- JSONCPP_STRING::const_iterator iter = comment.begin();
+ if (!indented_)
+ writeIndent();
+ const String& comment = root.getComment(commentBefore);
+ String::const_iterator iter = comment.begin();
while (iter != comment.end()) {
*sout_ << *iter;
- if (*iter == '\n' &&
- (iter != comment.end() && *(iter + 1) == '/'))
+ if (*iter == '\n' && ((iter + 1) != comment.end() && *(iter + 1) == '/'))
// writeIndent(); // would write extra newline
*sout_ << indentString_;
++iter;
@@ -1129,8 +1130,10 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
indented_ = false;
}
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
- if (cs_ == CommentStyle::None) return;
+void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(
+ Value const& root) {
+ if (cs_ == CommentStyle::None)
+ return;
if (root.hasComment(commentAfterOnSameLine))
*sout_ << " " + root.getComment(commentAfterOnSameLine);
@@ -1150,28 +1153,19 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
///////////////
// StreamWriter
-StreamWriter::StreamWriter()
- : sout_(NULL)
-{
-}
-StreamWriter::~StreamWriter()
-{
-}
-StreamWriter::Factory::~Factory()
-{}
-StreamWriterBuilder::StreamWriterBuilder()
-{
- setDefaults(&settings_);
-}
-StreamWriterBuilder::~StreamWriterBuilder()
-{}
-StreamWriter* StreamWriterBuilder::newStreamWriter() const
-{
- JSONCPP_STRING indentation = settings_["indentation"].asString();
- JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
- bool eyc = settings_["enableYAMLCompatibility"].asBool();
- bool dnp = settings_["dropNullPlaceholders"].asBool();
- bool usf = settings_["useSpecialFloats"].asBool();
+StreamWriter::StreamWriter() : sout_(nullptr) {}
+StreamWriter::~StreamWriter() = default;
+StreamWriter::Factory::~Factory() = default;
+StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
+StreamWriterBuilder::~StreamWriterBuilder() = default;
+StreamWriter* StreamWriterBuilder::newStreamWriter() const {
+ const String indentation = settings_["indentation"].asString();
+ const String cs_str = settings_["commentStyle"].asString();
+ const String pt_str = settings_["precisionType"].asString();
+ const bool eyc = settings_["enableYAMLCompatibility"].asBool();
+ const bool dnp = settings_["dropNullPlaceholders"].asBool();
+ const bool usf = settings_["useSpecialFloats"].asBool();
+ const bool emitUTF8 = settings_["emitUTF8"].asBool();
unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
@@ -1181,74 +1175,80 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
} else {
throwRuntimeError("commentStyle must be 'All' or 'None'");
}
- JSONCPP_STRING colonSymbol = " : ";
+ PrecisionType precisionType(significantDigits);
+ if (pt_str == "significant") {
+ precisionType = PrecisionType::significantDigits;
+ } else if (pt_str == "decimal") {
+ precisionType = PrecisionType::decimalPlaces;
+ } else {
+ throwRuntimeError("precisionType must be 'significant' or 'decimal'");
+ }
+ String colonSymbol = " : ";
if (eyc) {
colonSymbol = ": ";
} else if (indentation.empty()) {
colonSymbol = ":";
}
- JSONCPP_STRING nullSymbol = "null";
+ String nullSymbol = "null";
if (dnp) {
nullSymbol.clear();
}
- if (pre > 17) pre = 17;
- JSONCPP_STRING endingLineFeedSymbol;
- return new BuiltStyledStreamWriter(
- indentation, cs,
- colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
+ if (pre > 17)
+ pre = 17;
+ String endingLineFeedSymbol;
+ return new BuiltStyledStreamWriter(indentation, cs, colonSymbol, nullSymbol,
+ endingLineFeedSymbol, usf, emitUTF8, pre,
+ precisionType);
}
-static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
-{
- valid_keys->clear();
- valid_keys->insert("indentation");
- valid_keys->insert("commentStyle");
- valid_keys->insert("enableYAMLCompatibility");
- valid_keys->insert("dropNullPlaceholders");
- valid_keys->insert("useSpecialFloats");
- valid_keys->insert("precision");
-}
-bool StreamWriterBuilder::validate(Json::Value* invalid) const
-{
- Json::Value my_invalid;
- if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
- Json::Value& inv = *invalid;
- std::set<JSONCPP_STRING> valid_keys;
- getValidWriterKeys(&valid_keys);
- Value::Members keys = settings_.getMemberNames();
- size_t n = keys.size();
- for (size_t i = 0; i < n; ++i) {
- JSONCPP_STRING const& key = keys[i];
- if (valid_keys.find(key) == valid_keys.end()) {
- inv[key] = settings_[key];
- }
+
+bool StreamWriterBuilder::validate(Json::Value* invalid) const {
+ static const auto& valid_keys = *new std::set<String>{
+ "indentation",
+ "commentStyle",
+ "enableYAMLCompatibility",
+ "dropNullPlaceholders",
+ "useSpecialFloats",
+ "emitUTF8",
+ "precision",
+ "precisionType",
+ };
+ for (auto si = settings_.begin(); si != settings_.end(); ++si) {
+ auto key = si.name();
+ if (valid_keys.count(key))
+ continue;
+ if (invalid)
+ (*invalid)[std::move(key)] = *si;
+ else
+ return false;
}
- return 0u == inv.size();
+ return invalid ? invalid->empty() : true;
}
-Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
-{
+
+Value& StreamWriterBuilder::operator[](const String& key) {
return settings_[key];
}
// static
-void StreamWriterBuilder::setDefaults(Json::Value* settings)
-{
+void StreamWriterBuilder::setDefaults(Json::Value* settings) {
//! [StreamWriterBuilderDefaults]
(*settings)["commentStyle"] = "All";
(*settings)["indentation"] = "\t";
(*settings)["enableYAMLCompatibility"] = false;
(*settings)["dropNullPlaceholders"] = false;
(*settings)["useSpecialFloats"] = false;
+ (*settings)["emitUTF8"] = false;
(*settings)["precision"] = 17;
+ (*settings)["precisionType"] = "significant";
//! [StreamWriterBuilderDefaults]
}
-JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
- JSONCPP_OSTRINGSTREAM sout;
- StreamWriterPtr const writer(builder.newStreamWriter());
+String writeString(StreamWriter::Factory const& factory, Value const& root) {
+ OStringStream sout;
+ StreamWriterPtr const writer(factory.newStreamWriter());
writer->write(root, &sout);
return sout.str();
}
-JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
+OStream& operator<<(OStream& sout, Value const& root) {
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);