Update jsoncpp to 1.8.4 (#7172)

This commit is contained in:
Loïc Blot 2018-03-26 17:44:54 +02:00 committed by SmallJoker
parent b0fef16a27
commit 040b878cd5
3 changed files with 187 additions and 164 deletions

@ -1,4 +1,4 @@
/// Json-cpp amalgated forward header (http://jsoncpp.sourceforge.net/). /// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).
/// It is intended to be used with #include "json/json-forwards.h" /// It is intended to be used with #include "json/json-forwards.h"
/// This header provides forward declaration for all JsonCpp types. /// This header provides forward declaration for all JsonCpp types.
@ -73,9 +73,9 @@ license you like.
#ifndef JSON_FORWARD_AMALGATED_H_INCLUDED #ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED
# define JSON_FORWARD_AMALGATED_H_INCLUDED # define JSON_FORWARD_AMALGAMATED_H_INCLUDED
/// If defined, indicates that the source file is amalgated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION #define JSON_IS_AMALGAMATION
@ -110,9 +110,9 @@ license you like.
#define JSON_USE_EXCEPTION 1 #define JSON_USE_EXCEPTION 1
#endif #endif
/// If defined, indicates that the source file is amalgated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgated header. /// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION // #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL #ifdef JSON_IN_CPPTL
@ -163,7 +163,7 @@ license you like.
#endif // defined(_MSC_VER) #endif // defined(_MSC_VER)
// In c++11 the override keyword allows you to explicity define that a function // In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more // is intended to override the base-class version. This makes the code more
// managable and fixes a set of common hard-to-find bugs. // managable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@ -330,4 +330,4 @@ class ValueConstIterator;
#endif //ifndef JSON_FORWARD_AMALGATED_H_INCLUDED #endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED

@ -1,4 +1,4 @@
/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/). /// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).
/// It is intended to be used with #include "json/json.h" /// It is intended to be used with #include "json/json.h"
// ////////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////////
@ -72,9 +72,9 @@ license you like.
#ifndef JSON_AMALGATED_H_INCLUDED #ifndef JSON_AMALGAMATED_H_INCLUDED
# define JSON_AMALGATED_H_INCLUDED # define JSON_AMALGAMATED_H_INCLUDED
/// If defined, indicates that the source file is amalgated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
#define JSON_IS_AMALGAMATION #define JSON_IS_AMALGAMATION
@ -87,10 +87,10 @@ license you like.
#ifndef JSON_VERSION_H_INCLUDED #ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED # define JSON_VERSION_H_INCLUDED
# define JSONCPP_VERSION_STRING "1.8.3" # define JSONCPP_VERSION_STRING "1.8.4"
# define JSONCPP_VERSION_MAJOR 1 # define JSONCPP_VERSION_MAJOR 1
# define JSONCPP_VERSION_MINOR 8 # define JSONCPP_VERSION_MINOR 8
# define JSONCPP_VERSION_PATCH 3 # define JSONCPP_VERSION_PATCH 4
# define JSONCPP_VERSION_QUALIFIER # define JSONCPP_VERSION_QUALIFIER
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8)) # define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
@ -143,9 +143,9 @@ license you like.
#define JSON_USE_EXCEPTION 1 #define JSON_USE_EXCEPTION 1
#endif #endif
/// If defined, indicates that the source file is amalgated /// If defined, indicates that the source file is amalgamated
/// to prevent private header inclusion. /// to prevent private header inclusion.
/// Remarks: it is automatically defined in the generated amalgated header. /// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION // #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL #ifdef JSON_IN_CPPTL
@ -196,7 +196,7 @@ license you like.
#endif // defined(_MSC_VER) #endif // defined(_MSC_VER)
// In c++11 the override keyword allows you to explicity define that a function // In c++11 the override keyword allows you to explicitly define that a function
// is intended to override the base-class version. This makes the code more // is intended to override the base-class version. This makes the code more
// managable and fixes a set of common hard-to-find bugs. // managable and fixes a set of common hard-to-find bugs.
#if __cplusplus >= 201103L #if __cplusplus >= 201103L
@ -561,7 +561,7 @@ enum CommentPlacement {
/** \brief Lightweight wrapper to tag static string. /** \brief Lightweight wrapper to tag static string.
* *
* Value constructor and objectValue member assignement takes advantage of the * Value constructor and objectValue member assignment takes advantage of the
* StaticString and avoid the cost of string duplication when storing the * StaticString and avoid the cost of string duplication when storing the
* string or the member name. * string or the member name.
* *
@ -635,6 +635,9 @@ public:
typedef Json::LargestUInt LargestUInt; typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex; typedef Json::ArrayIndex ArrayIndex;
// Required for boost integration, e. g. BOOST_TEST
typedef std::string value_type;
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value(). static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
static Value const& nullSingleton(); ///< Prefer this to null or nullRef. static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
@ -842,8 +845,8 @@ Json::Value obj_value(Json::objectValue); // {}
/// otherwise, false. /// otherwise, false.
bool empty() const; bool empty() const;
/// Return isNull() /// Return !isNull()
bool operator!() const; explicit operator bool() const;
/// Remove all object members and array elements. /// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue /// \pre type() is arrayValue, objectValue, or nullValue
@ -963,13 +966,11 @@ Json::Value obj_value(Json::objectValue); // {}
/// \pre type() is objectValue or nullValue /// \pre type() is objectValue or nullValue
/// \post type() is unchanged /// \post type() is unchanged
/// \deprecated /// \deprecated
JSONCPP_DEPRECATED("") void removeMember(const char* key);
Value removeMember(const char* key);
/// Same as removeMember(const char*) /// Same as removeMember(const char*)
/// \param key may contain embedded nulls. /// \param key may contain embedded nulls.
/// \deprecated /// \deprecated
JSONCPP_DEPRECATED("") void removeMember(const JSONCPP_STRING& key);
Value removeMember(const JSONCPP_STRING& key);
/// Same as removeMember(const char* begin, const char* end, Value* removed), /// Same as removeMember(const char* begin, const char* end, Value* removed),
/// but 'key' is null-terminated. /// but 'key' is null-terminated.
bool removeMember(const char* key, Value* removed); bool removeMember(const char* key, Value* removed);
@ -1786,7 +1787,7 @@ JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
// Disable warning C4251: <data member>: <type> needs to have dll-interface to // Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by... // be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) && defined(_MSC_VER)
#pragma warning(push) #pragma warning(push)
#pragma warning(disable : 4251) #pragma warning(disable : 4251)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@ -1870,7 +1871,7 @@ public:
- "dropNullPlaceholders": false or true - "dropNullPlaceholders": false or true
- Drop the "null" string from the writer's output for nullValues. - Drop the "null" string from the writer's output for nullValues.
Strictly speaking, this is not valid JSON. But when the output is being Strictly speaking, this is not valid JSON. But when the output is being
fed to a browser's Javascript, it makes for smaller output and the fed to a browser's JavaScript, it makes for smaller output and the
browser can handle the output just fine. browser can handle the output just fine.
- "useSpecialFloats": false or true - "useSpecialFloats": false or true
- If true, outputs non-finite floating point values in the following way: - If true, outputs non-finite floating point values in the following way:
@ -1927,8 +1928,11 @@ public:
* \sa Reader, Value * \sa Reader, Value
* \deprecated Use StreamWriterBuilder. * \deprecated Use StreamWriterBuilder.
*/ */
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer { class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter : public Writer {
public: public:
FastWriter(); FastWriter();
~FastWriter() JSONCPP_OVERRIDE {} ~FastWriter() JSONCPP_OVERRIDE {}
@ -1937,7 +1941,7 @@ public:
/** \brief Drop the "null" string from the writer's output for nullValues. /** \brief Drop the "null" string from the writer's output for nullValues.
* Strictly speaking, this is not valid JSON. But when the output is being * Strictly speaking, this is not valid JSON. But when the output is being
* fed to a browser's Javascript, it makes for smaller output and the * fed to a browser's JavaScript, it makes for smaller output and the
* browser can handle the output just fine. * browser can handle the output just fine.
*/ */
void dropNullPlaceholders(); void dropNullPlaceholders();
@ -1951,10 +1955,13 @@ private:
void writeValue(const Value& value); void writeValue(const Value& value);
JSONCPP_STRING document_; JSONCPP_STRING document_;
bool yamlCompatiblityEnabled_; bool yamlCompatibilityEnabled_;
bool dropNullPlaceholders_; bool dropNullPlaceholders_;
bool omitEndingLineFeed_; bool omitEndingLineFeed_;
}; };
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
*human friendly way. *human friendly way.
@ -1980,6 +1987,10 @@ private:
* \sa Reader, Value, Value::setComment() * \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder. * \deprecated Use StreamWriterBuilder.
*/ */
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer { class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledWriter : public Writer {
public: public:
StyledWriter(); StyledWriter();
@ -1995,7 +2006,7 @@ public: // overridden from Writer
private: private:
void writeValue(const Value& value); void writeValue(const Value& value);
void writeArrayValue(const Value& value); void writeArrayValue(const Value& value);
bool isMultineArray(const Value& value); bool isMultilineArray(const Value& value);
void pushValue(const JSONCPP_STRING& value); void pushValue(const JSONCPP_STRING& value);
void writeIndent(); void writeIndent();
void writeWithIndent(const JSONCPP_STRING& value); void writeWithIndent(const JSONCPP_STRING& value);
@ -2015,6 +2026,9 @@ private:
unsigned int indentSize_; unsigned int indentSize_;
bool addChildValues_; bool addChildValues_;
}; };
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a /** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
human friendly way, human friendly way,
@ -2041,6 +2055,10 @@ private:
* \sa Reader, Value, Value::setComment() * \sa Reader, Value, Value::setComment()
* \deprecated Use StreamWriterBuilder. * \deprecated Use StreamWriterBuilder.
*/ */
#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable:4996) // Deriving from deprecated class
#endif
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter { class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API StyledStreamWriter {
public: public:
/** /**
@ -2061,7 +2079,7 @@ public:
private: private:
void writeValue(const Value& value); void writeValue(const Value& value);
void writeArrayValue(const Value& value); void writeArrayValue(const Value& value);
bool isMultineArray(const Value& value); bool isMultilineArray(const Value& value);
void pushValue(const JSONCPP_STRING& value); void pushValue(const JSONCPP_STRING& value);
void writeIndent(); void writeIndent();
void writeWithIndent(const JSONCPP_STRING& value); void writeWithIndent(const JSONCPP_STRING& value);
@ -2082,6 +2100,9 @@ private:
bool addChildValues_ : 1; bool addChildValues_ : 1;
bool indented_ : 1; bool indented_ : 1;
}; };
#if defined(_MSC_VER)
#pragma warning(pop)
#endif
#if defined(JSON_HAS_INT64) #if defined(JSON_HAS_INT64)
JSONCPP_STRING JSON_API valueToString(Int value); JSONCPP_STRING JSON_API valueToString(Int value);
@ -2183,4 +2204,4 @@ JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
#endif //ifndef JSON_AMALGATED_H_INCLUDED #endif //ifndef JSON_AMALGAMATED_H_INCLUDED

@ -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" /// 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; 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 { enum {
/// Constant that specify the size of the buffer that must be passed to /// Constant that specify the size of the buffer that must be passed to
/// uintToString. /// uintToString.
@ -160,7 +157,7 @@ enum {
typedef char UIntToStringBuffer[uintToStringBufferSize]; typedef char UIntToStringBuffer[uintToStringBufferSize];
/** Converts an unsigned integer to string. /** 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. * @param current Input/Output string buffer.
* Must have at least uintToStringBufferSize chars free. * Must have at least uintToStringBufferSize chars free.
*/ */
@ -1454,7 +1451,7 @@ bool OurReader::readToken(Token& token) {
token.type_ = tokenString; token.type_ = tokenString;
ok = readStringSingleQuote(); ok = readStringSingleQuote();
break; break;
} // else continue } // else fall through
case '/': case '/':
token.type_ = tokenComment; token.type_ = tokenComment;
ok = readComment(); ok = readComment();
@ -2269,10 +2266,6 @@ JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
JSONCPP_STRING errs; JSONCPP_STRING errs;
bool ok = parseFromStream(b, sin, &root, &errs); bool ok = parseFromStream(b, sin, &root, &errs);
if (!ok) { if (!ok) {
fprintf(stderr,
"Error from reader: %s",
errs.c_str());
throwRuntimeError(errs); throwRuntimeError(errs);
} }
return sin; return sin;
@ -3438,7 +3431,7 @@ bool Value::empty() const {
return false; return false;
} }
bool Value::operator!() const { return isNull(); } Value::operator bool() const { return ! isNull(); }
void Value::clear() { void Value::clear() {
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue || 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; } Value& Value::append(const Value& value) { return (*this)[size()] = value; }
#if JSON_HAS_RVALUE_REFERENCES #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 #endif
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const 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); 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, JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
"in Json::Value::removeMember(): requires objectValue"); "in Json::Value::removeMember(): requires objectValue");
if (type_ == nullValue) if (type_ == nullValue)
return nullSingleton(); return;
Value removed; // null CZString actualKey(key, unsigned(strlen(key)), CZString::noDuplication);
removeMember(key, key + strlen(key), &removed); value_.map_->erase(actualKey);
return removed; // still null if removeMember() did nothing
} }
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) { bool Value::removeIndex(ArrayIndex index, Value* removed) {
@ -4233,24 +4225,6 @@ typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
typedef std::auto_ptr<StreamWriter> StreamWriterPtr; typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif #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) { JSONCPP_STRING valueToString(LargestInt value) {
UIntToStringBuffer buffer; UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer); char* current = buffer + sizeof(buffer);
@ -4295,10 +4269,10 @@ JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int p
int len = -1; int len = -1;
char formatString[15]; 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 // 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. // concepts of reals and integers.
if (isfinite(value)) { if (isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), formatString, 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 valueToString(bool value) { return value ? "true" : "false"; }
JSONCPP_STRING valueToQuotedString(const char* value) { static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
if (value == NULL) assert(s || !n);
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);
char const* const end = s + n; char const* const end = s + n;
for (char const* cur = s; cur < end; ++cur) { for (char const* cur = s; cur < end; ++cur) {
int const c = *cur; if (*cur == '\\' || *cur == '\"' || *cur < ' '
for (char const* a = accept; *a; ++a) { || static_cast<unsigned char>(*cur) < 0x80)
if (*a == c) { return true;
return cur;
}
}
} }
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) { static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
if (value == NULL) if (value == NULL)
return ""; return "";
// Not sure how to handle unicode...
if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL && if (!isAnyCharRequiredQuoting(value, length))
!containsControlCharacter0(value, length))
return JSONCPP_STRING("\"") + value + "\""; return JSONCPP_STRING("\"") + value + "\"";
// We have to walk value and escape any special characters. // We have to walk value and escape any special characters.
// Appending to JSONCPP_STRING is not efficient, but this should be rare. // 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. // sequence.
// Should add a flag to allow this compatibility mode and prevent this // Should add a flag to allow this compatibility mode and prevent this
// sequence from occurring. // sequence from occurring.
default: default: {
if ((isControlCharacter(*c)) || (*c == 0)) { unsigned int cp = utf8ToCodepoint(c, end);
JSONCPP_OSTRINGSTREAM oss; // don't escape non-control characters
oss << "\\u" << std::hex << std::uppercase << std::setfill('0') // (short escape sequence are applied above)
<< std::setw(4) << static_cast<int>(*c); if (cp < 0x80 && cp >= 0x20)
result += oss.str(); result += static_cast<char>(cp);
} else { else if (cp < 0x10000) { // codepoint is in Basic Multilingual Plane
result += *c; 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; break;
} }
@ -4468,6 +4466,10 @@ static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
return result; return result;
} }
JSONCPP_STRING valueToQuotedString(const char* value) {
return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
}
// Class Writer // Class Writer
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
Writer::~Writer() {} Writer::~Writer() {}
@ -4476,10 +4478,10 @@ Writer::~Writer() {}
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
FastWriter::FastWriter() FastWriter::FastWriter()
: yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false), : yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
omitEndingLineFeed_(false) {} omitEndingLineFeed_(false) {}
void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; } void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; } void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
@ -4539,7 +4541,7 @@ void FastWriter::writeValue(const Value& value) {
if (it != members.begin()) if (it != members.begin())
document_ += ','; document_ += ',';
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())); document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += yamlCompatiblityEnabled_ ? ": " : ":"; document_ += yamlCompatibilityEnabled_ ? ": " : ":";
writeValue(value[name]); writeValue(value[name]);
} }
document_ += '}'; document_ += '}';
@ -4628,7 +4630,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
if (size == 0) if (size == 0)
pushValue("[]"); pushValue("[]");
else { else {
bool isArrayMultiLine = isMultineArray(value); bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) { if (isArrayMultiLine) {
writeWithIndent("["); writeWithIndent("[");
indent(); 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(); ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_; bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear(); childValues_.clear();
@ -4845,7 +4847,7 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
if (size == 0) if (size == 0)
pushValue("[]"); pushValue("[]");
else { else {
bool isArrayMultiLine = isMultineArray(value); bool isArrayMultiLine = isMultilineArray(value);
if (isArrayMultiLine) { if (isArrayMultiLine) {
writeWithIndent("["); writeWithIndent("[");
indent(); 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(); ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_; bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear(); childValues_.clear();
@ -5002,7 +5004,7 @@ struct BuiltStyledStreamWriter : public StreamWriter
private: private:
void writeValue(Value const& value); void writeValue(Value const& value);
void writeArrayValue(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 pushValue(JSONCPP_STRING const& value);
void writeIndent(); void writeIndent();
void writeWithIndent(JSONCPP_STRING const& value); void writeWithIndent(JSONCPP_STRING const& value);
@ -5126,7 +5128,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
if (size == 0) if (size == 0)
pushValue("[]"); pushValue("[]");
else { else {
bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value); bool isMultiLine = (cs_ == CommentStyle::All) || isMultilineArray(value);
if (isMultiLine) { if (isMultiLine) {
writeWithIndent("["); writeWithIndent("[");
indent(); 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(); ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_; bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear(); childValues_.clear();