summaryrefslogtreecommitdiff
path: root/lib/jsoncpp/jsoncpp.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/jsoncpp/jsoncpp.cpp')
-rw-r--r--lib/jsoncpp/jsoncpp.cpp266
1 files changed, 134 insertions, 132 deletions
diff --git a/lib/jsoncpp/jsoncpp.cpp b/lib/jsoncpp/jsoncpp.cpp
index a85e280ed..507a1c6ad 100644
--- a/lib/jsoncpp/jsoncpp.cpp
+++ b/lib/jsoncpp/jsoncpp.cpp
@@ -1,4 +1,4 @@
-/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
+/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).
/// It is intended to be used with #include "json/json.h"
// //////////////////////////////////////////////////////////////////////
@@ -147,9 +147,6 @@ static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
return result;
}
-/// Returns true if ch is a control character (in range [1,31]).
-static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
-
enum {
/// Constant that specify the size of the buffer that must be passed to
/// uintToString.
@@ -160,7 +157,7 @@ enum {
typedef char UIntToStringBuffer[uintToStringBufferSize];
/** Converts an unsigned integer to string.
- * @param value Unsigned interger to convert to string
+ * @param value Unsigned integer to convert to string
* @param current Input/Output string buffer.
* Must have at least uintToStringBufferSize chars free.
*/
@@ -1454,7 +1451,7 @@ bool OurReader::readToken(Token& token) {
token.type_ = tokenString;
ok = readStringSingleQuote();
break;
- } // else continue
+ } // else fall through
case '/':
token.type_ = tokenComment;
ok = readComment();
@@ -2269,10 +2266,6 @@ JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) {
- fprintf(stderr,
- "Error from reader: %s",
- errs.c_str());
-
throwRuntimeError(errs);
}
return sin;
@@ -3438,7 +3431,7 @@ bool Value::empty() const {
return false;
}
-bool Value::operator!() const { return isNull(); }
+Value::operator bool() const { return ! isNull(); }
void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
@@ -3624,7 +3617,7 @@ Value const& Value::operator[](CppTL::ConstString const& key) const
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
#if JSON_HAS_RVALUE_REFERENCES
- Value& Value::append(Value&& value) { return (*this)[size()] = value; }
+ Value& Value::append(Value&& value) { return (*this)[size()] = std::move(value); }
#endif
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
@@ -3663,20 +3656,19 @@ bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
{
return removeMember(key.data(), key.data() + key.length(), removed);
}
-Value Value::removeMember(const char* key)
+void Value::removeMember(const char* key)
{
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue)
- return nullSingleton();
+ return;
- Value removed; // null
- removeMember(key, key + strlen(key), &removed);
- return removed; // still null if removeMember() did nothing
+ CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
+ value_.map_->erase(actualKey);
}
-Value Value::removeMember(const JSONCPP_STRING& key)
+void Value::removeMember(const JSONCPP_STRING& key)
{
- return removeMember(key.c_str());
+ removeMember(key.c_str());
}
bool Value::removeIndex(ArrayIndex index, Value* removed) {
@@ -4233,24 +4225,6 @@ typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#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) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
@@ -4295,10 +4269,10 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
int len = -1;
char formatString[15];
- snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
+ snprintf(formatString, sizeof(formatString), "%%.%ug", precision);
// 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);
@@ -4328,89 +4302,103 @@ JSONCPP_STRING valueToString(double value) { return valueToString(value, false,
JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
-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;
- }
- }
- result += "\"";
- 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 bool isAnyCharRequiredQuoting(char const* s, size_t n) {
+ assert(s || !n);
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;
- }
- }
+ if (*cur == '\\' || *cur == '\"' || *cur < ' '
+ || static_cast<unsigned char>(*cur) < 0x80)
+ return true;
}
- return NULL;
+ return false;
}
+
+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;
+ }
+
+ 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) << 24)
+ | ((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 JSONCPP_STRING toHex16Bit(unsigned int x) {
+ const unsigned int hi = (x >> 8) & 0xff;
+ const unsigned int lo = x & 0xff;
+ JSONCPP_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;
+}
+
static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
if (value == NULL)
return "";
- // Not sure how to handle unicode...
- if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
- !containsControlCharacter0(value, length))
+
+ if (!isAnyCharRequiredQuoting(value, length))
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.
@@ -4452,14 +4440,24 @@ 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();
- } else {
- result += *c;
+ default: {
+ unsigned int cp = utf8ToCodepoint(c, end);
+ // don't escape non-control characters
+ // (short escape sequence are applied above)
+ if (cp < 0x80 && cp >= 0x20)
+ result += static_cast<char>(cp);
+ else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
+ result += "\\u";
+ result += toHex16Bit(cp);
+ }
+ else { // codepoint is not in Basic Multilingual Plane
+ // convert to surrogate pair first
+ cp -= 0x10000;
+ result += "\\u";
+ result += toHex16Bit((cp >> 10) + 0xD800);
+ result += "\\u";
+ result += toHex16Bit((cp & 0x3FF) + 0xDC00);
+ }
}
break;
}
@@ -4468,6 +4466,10 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
return result;
}
+JSONCPP_STRING valueToQuotedString(const char* value) {
+ return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
+}
+
// Class Writer
// //////////////////////////////////////////////////////////////////
Writer::~Writer() {}
@@ -4476,10 +4478,10 @@ Writer::~Writer() {}
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
- : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
+ : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
omitEndingLineFeed_(false) {}
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
+void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
@@ -4539,7 +4541,7 @@ void FastWriter::writeValue(const Value& value) {
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
- document_ += yamlCompatiblityEnabled_ ? ": " : ":";
+ document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
document_ += '}';
@@ -4628,7 +4630,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -4666,7 +4668,7 @@ 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();
@@ -4845,7 +4847,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (size == 0)
pushValue("[]");
else {
- bool isArrayMultiLine = isMultineArray(value);
+ bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) {
writeWithIndent("[");
indent();
@@ -4885,7 +4887,7 @@ 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();
@@ -5002,7 +5004,7 @@ struct BuiltStyledStreamWriter : public StreamWriter
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
- bool isMultineArray(Value const& value);
+ bool isMultilineArray(Value const& value);
void pushValue(JSONCPP_STRING const& value);
void writeIndent();
void writeWithIndent(JSONCPP_STRING const& value);
@@ -5126,7 +5128,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();
@@ -5168,7 +5170,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
}
}
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
+bool BuiltStyledStreamWriter::isMultilineArray(Value const& value) {
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();