Import lib jsoncpp version 1.7.0

This commit is contained in:
2016-02-27 00:24:38 +01:00
parent 3bc376da33
commit 2fd70e2c68
64 changed files with 2462 additions and 916 deletions

View File

@@ -2,4 +2,4 @@ ADD_SUBDIRECTORY(lib_json)
IF(JSONCPP_WITH_TESTS)
ADD_SUBDIRECTORY(jsontestrunner)
ADD_SUBDIRECTORY(test_lib_json)
ENDIF(JSONCPP_WITH_TESTS)
ENDIF()

View File

@@ -1,18 +1,15 @@
FIND_PACKAGE(PythonInterp 2.6)
IF(JSONCPP_LIB_BUILD_SHARED)
ADD_DEFINITIONS( -DJSON_DLL )
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ADD_EXECUTABLE(jsontestrunner_exe
main.cpp
)
IF(JSONCPP_LIB_BUILD_SHARED)
IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS( -DJSON_DLL )
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib)
ELSE(JSONCPP_LIB_BUILD_SHARED)
ELSE(BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib_static)
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ENDIF()
SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
@@ -25,4 +22,4 @@ IF(PYTHONINTERP_FOUND)
DEPENDS jsontestrunner_exe jsoncpp_test
)
ADD_CUSTOM_TARGET(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
ENDIF(PYTHONINTERP_FOUND)
ENDIF()

View File

@@ -57,12 +57,13 @@ static std::string readInputTestFile(const char* path) {
if (!file)
return std::string("");
fseek(file, 0, SEEK_END);
long size = ftell(file);
long const size = ftell(file);
unsigned long const usize = static_cast<unsigned long const>(size);
fseek(file, 0, SEEK_SET);
std::string text;
char* buffer = new char[size + 1];
buffer[size] = 0;
if (fread(buffer, 1, size, file) == (unsigned long)size)
if (fread(buffer, 1, usize, file) == usize)
text = buffer;
fclose(file);
delete[] buffer;
@@ -104,8 +105,8 @@ printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
break;
case Json::arrayValue: {
fprintf(fout, "%s=[]\n", path.c_str());
int size = value.size();
for (int index = 0; index < size; ++index) {
Json::ArrayIndex size = value.size();
for (Json::ArrayIndex index = 0; index < size; ++index) {
static char buffer[16];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
sprintf_s(buffer, sizeof(buffer), "[%d]", index);
@@ -310,12 +311,12 @@ static int runTest(Options const& opts)
}
int main(int argc, const char* argv[]) {
Options opts;
try {
int exitCode = parseCommandLine(argc, argv, &opts);
if (exitCode != 0) {
printf("Failed to parse command-line.");
return exitCode;
}
try {
return runTest(opts);
}
catch (const std::exception& e) {

View File

@@ -1,15 +1,8 @@
OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF)
OPTION(JSONCPP_LIB_BUILD_STATIC "Build jsoncpp_lib static library." ON)
IF(BUILD_SHARED_LIBS)
SET(JSONCPP_LIB_BUILD_SHARED ON)
ENDIF(BUILD_SHARED_LIBS)
if( CMAKE_COMPILER_IS_GNUCXX )
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
#-Werror=* was introduced -after- GCC 4.1.2
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
@@ -44,13 +37,14 @@ IF(JSONCPP_WITH_CMAKE_PACKAGE)
SET(INSTALL_EXPORT EXPORT jsoncpp)
ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
SET(INSTALL_EXPORT)
ENDIF(JSONCPP_WITH_CMAKE_PACKAGE)
ENDIF()
IF(JSONCPP_LIB_BUILD_SHARED)
IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources})
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
@@ -61,14 +55,15 @@ IF(JSONCPP_LIB_BUILD_SHARED)
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>)
ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
ENDIF()
ENDIF()
IF(JSONCPP_LIB_BUILD_STATIC)
IF(BUILD_STATIC_LIBS)
ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources})
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp )
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT}
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
@@ -80,6 +75,6 @@ IF(JSONCPP_LIB_BUILD_STATIC)
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
)
ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
ENDIF()
ENDIF()

View File

@@ -4,9 +4,9 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
#include <jsoncpp/assertions.h>
#include <jsoncpp/reader.h>
#include <jsoncpp/value.h>
#include <json/assertions.h>
#include <json/reader.h>
#include <json/value.h>
#include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <utility>
@@ -17,10 +17,27 @@
#include <sstream>
#include <memory>
#include <set>
#include <limits>
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
#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
#endif
#if defined(__QNXNTO__)
#define sscanf std::sscanf
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
// Disable warning about strdup being deprecated.
@@ -32,7 +49,7 @@ static int stackDepth_g = 0; // see readValue()
namespace Json {
#if __cplusplus >= 201103L
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<CharReader> CharReaderPtr;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
@@ -353,7 +370,7 @@ bool Reader::readComment() {
static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
std::string normalized;
normalized.reserve(end - begin);
normalized.reserve(static_cast<size_t>(end - begin));
Reader::Location current = begin;
while (current != end) {
char c = *current++;
@@ -555,7 +572,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
++current;
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
Value::LargestUInt maxIntegerValue =
isNegative ? Value::LargestUInt(-Value::minLargestInt)
isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
Value::LargestUInt value = 0;
@@ -563,7 +580,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
Value::UInt digit(c - '0');
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, b) this is the last digit, and
@@ -576,7 +593,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
}
value = value * 10 + digit;
}
if (isNegative)
if (isNegative && value == maxIntegerValue)
decoded = Value::minLargestInt;
else if (isNegative)
decoded = -Value::LargestInt(value);
else if (value <= Value::LargestUInt(Value::maxInt))
decoded = Value::LargestInt(value);
@@ -597,33 +616,9 @@ bool Reader::decodeDouble(Token& token) {
bool Reader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
const int bufferSize = 32;
int count;
int length = int(token.end_ - token.start_);
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
return addError("Unable to parse token length", token);
}
// Avoid using a string constant for the format control string given to
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
// info:
//
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
char format[] = "%lf";
if (length <= bufferSize) {
Char buffer[bufferSize + 1];
memcpy(buffer, token.start_, length);
buffer[length] = 0;
count = sscanf(buffer, format, &value);
} else {
std::string buffer(token.start_, token.end_);
count = sscanf(buffer.c_str(), format, &value);
}
if (count != 1)
std::string buffer(token.start_, token.end_);
std::istringstream is(buffer);
if (!(is >> value))
return addError("'" + std::string(token.start_, token.end_) +
"' is not a number.",
token);
@@ -643,7 +638,7 @@ bool Reader::decodeString(Token& token) {
}
bool Reader::decodeString(Token& token, std::string& decoded) {
decoded.reserve(token.end_ - token.start_ - 2);
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
@@ -727,13 +722,13 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
bool Reader::decodeUnicodeEscapeSequence(Token& token,
Location& current,
Location end,
unsigned int& unicode) {
unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
"Bad unicode escape sequence in string: four digits expected.",
token,
current);
unicode = 0;
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
unicode *= 16;
@@ -749,6 +744,7 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
token,
current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
@@ -763,7 +759,7 @@ Reader::addError(const std::string& message, Token& token, Location extra) {
}
bool Reader::recoverFromError(TokenType skipUntilToken) {
int errorCount = int(errors_.size());
size_t const errorCount = errors_.size();
Token skip;
for (;;) {
if (!readToken(skip))
@@ -817,15 +813,7 @@ std::string Reader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
#if defined(WINCE)
_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#else
sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#endif
#else
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#endif
return buffer;
}
@@ -866,7 +854,7 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
}
bool Reader::pushError(const Value& value, const std::string& message) {
size_t length = end_ - begin_;
ptrdiff_t const length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length)
return false;
@@ -883,7 +871,7 @@ bool Reader::pushError(const Value& value, const std::string& message) {
}
bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
size_t length = end_ - begin_;
ptrdiff_t const length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length
|| extra.getOffsetLimit() > length)
@@ -908,7 +896,6 @@ bool Reader::good() const {
class OurFeatures {
public:
static OurFeatures all();
OurFeatures();
bool allowComments_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
@@ -916,20 +903,13 @@ public:
bool allowSingleQuotes_;
bool failIfExtra_;
bool rejectDupKeys_;
bool allowSpecialFloats_;
int stackLimit_;
}; // OurFeatures
// exact copy of Implementation of class Features
// ////////////////////////////////
OurFeatures::OurFeatures()
: allowComments_(true), strictRoot_(false)
, allowDroppedNullPlaceholders_(false), allowNumericKeys_(false)
, allowSingleQuotes_(false)
, failIfExtra_(false)
{
}
OurFeatures OurFeatures::all() { return OurFeatures(); }
// Implementation of class Reader
@@ -941,8 +921,8 @@ public:
typedef char Char;
typedef const Char* Location;
struct StructuredError {
size_t offset_start;
size_t offset_limit;
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
std::string message;
};
@@ -972,6 +952,9 @@ private:
tokenTrue,
tokenFalse,
tokenNull,
tokenNaN,
tokenPosInf,
tokenNegInf,
tokenArraySeparator,
tokenMemberSeparator,
tokenComment,
@@ -1002,7 +985,7 @@ private:
bool readCppStyleComment();
bool readString();
bool readStringSingleQuote();
void readNumber();
bool readNumber(bool checkInf);
bool readValue();
bool readObject(Token& token);
bool readArray(Token& token);
@@ -1054,7 +1037,9 @@ private:
OurReader::OurReader(OurFeatures const& features)
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
lastValue_(), commentsBefore_(), features_(features), collectComments_() {
lastValue_(), commentsBefore_(),
stackDepth_(0),
features_(features), collectComments_() {
}
bool OurReader::parse(const char* beginDoc,
@@ -1156,6 +1141,30 @@ bool OurReader::readValue() {
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNaN:
{
Value v(std::numeric_limits<double>::quiet_NaN());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenPosInf:
{
Value v(std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenNegInf:
{
Value v(-std::numeric_limits<double>::infinity());
currentValue().swapPayload(v);
currentValue().setOffsetStart(token.start_ - begin_);
currentValue().setOffsetLimit(token.end_ - begin_);
}
break;
case tokenArraySeparator:
case tokenObjectEnd:
case tokenArrayEnd:
@@ -1236,9 +1245,16 @@ bool OurReader::readToken(Token& token) {
case '7':
case '8':
case '9':
case '-':
token.type_ = tokenNumber;
readNumber();
readNumber(false);
break;
case '-':
if (readNumber(true)) {
token.type_ = tokenNumber;
} else {
token.type_ = tokenNegInf;
ok = features_.allowSpecialFloats_ && match("nfinity", 7);
}
break;
case 't':
token.type_ = tokenTrue;
@@ -1252,6 +1268,22 @@ bool OurReader::readToken(Token& token) {
token.type_ = tokenNull;
ok = match("ull", 3);
break;
case 'N':
if (features_.allowSpecialFloats_) {
token.type_ = tokenNaN;
ok = match("aN", 2);
} else {
ok = false;
}
break;
case 'I':
if (features_.allowSpecialFloats_) {
token.type_ = tokenPosInf;
ok = match("nfinity", 7);
} else {
ok = false;
}
break;
case ',':
token.type_ = tokenArraySeparator;
break;
@@ -1352,8 +1384,12 @@ bool OurReader::readCppStyleComment() {
return true;
}
void OurReader::readNumber() {
bool OurReader::readNumber(bool checkInf) {
const char *p = current_;
if (checkInf && p != end_ && *p == 'I') {
current_ = ++p;
return false;
}
char c = '0'; // stopgap for already consumed character
// integral part
while (c >= '0' && c <= '9')
@@ -1372,6 +1408,7 @@ void OurReader::readNumber() {
while (c >= '0' && c <= '9')
c = (current_ = p) < end_ ? *p++ : 0;
}
return true;
}
bool OurReader::readString() {
Char c = 0;
@@ -1526,7 +1563,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
Value::UInt digit(c - '0');
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, b) this is the last digit, and
@@ -1562,12 +1599,13 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
double value = 0;
const int bufferSize = 32;
int count;
int length = int(token.end_ - token.start_);
ptrdiff_t const length = token.end_ - token.start_;
// Sanity check to avoid buffer overflow exploits.
if (length < 0) {
return addError("Unable to parse token length", token);
}
size_t const ulength = static_cast<size_t>(length);
// Avoid using a string constant for the format control string given to
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
@@ -1578,7 +1616,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
if (length <= bufferSize) {
Char buffer[bufferSize + 1];
memcpy(buffer, token.start_, length);
memcpy(buffer, token.start_, ulength);
buffer[length] = 0;
count = sscanf(buffer, format, &value);
} else {
@@ -1606,7 +1644,7 @@ bool OurReader::decodeString(Token& token) {
}
bool OurReader::decodeString(Token& token, std::string& decoded) {
decoded.reserve(token.end_ - token.start_ - 2);
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
Location current = token.start_ + 1; // skip '"'
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
@@ -1690,13 +1728,13 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
bool OurReader::decodeUnicodeEscapeSequence(Token& token,
Location& current,
Location end,
unsigned int& unicode) {
unsigned int& ret_unicode) {
if (end - current < 4)
return addError(
"Bad unicode escape sequence in string: four digits expected.",
token,
current);
unicode = 0;
int unicode = 0;
for (int index = 0; index < 4; ++index) {
Char c = *current++;
unicode *= 16;
@@ -1712,6 +1750,7 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
token,
current);
}
ret_unicode = static_cast<unsigned int>(unicode);
return true;
}
@@ -1726,7 +1765,7 @@ OurReader::addError(const std::string& message, Token& token, Location extra) {
}
bool OurReader::recoverFromError(TokenType skipUntilToken) {
int errorCount = int(errors_.size());
size_t errorCount = errors_.size();
Token skip;
for (;;) {
if (!readToken(skip))
@@ -1780,15 +1819,7 @@ std::string OurReader::getLocationLineAndColumn(Location location) const {
int line, column;
getLocationLineAndColumn(location, line, column);
char buffer[18 + 16 + 16 + 1];
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
#if defined(WINCE)
_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#else
sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#endif
#else
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
#endif
return buffer;
}
@@ -1824,7 +1855,7 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
}
bool OurReader::pushError(const Value& value, const std::string& message) {
size_t length = end_ - begin_;
ptrdiff_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length)
return false;
@@ -1841,7 +1872,7 @@ bool OurReader::pushError(const Value& value, const std::string& message) {
}
bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
size_t length = end_ - begin_;
ptrdiff_t length = end_ - begin_;
if(value.getOffsetStart() > length
|| value.getOffsetLimit() > length
|| extra.getOffsetLimit() > length)
@@ -1873,9 +1904,9 @@ public:
: collectComments_(collectComments)
, reader_(features)
{}
virtual bool parse(
bool parse(
char const* beginDoc, char const* endDoc,
Value* root, std::string* errs) {
Value* root, std::string* errs) override {
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
if (errs) {
*errs = reader_.getFormattedErrorMessages();
@@ -1902,6 +1933,7 @@ CharReader* CharReaderBuilder::newCharReader() const
features.stackLimit_ = settings_["stackLimit"].asInt();
features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<std::string>* valid_keys)
@@ -1916,6 +1948,7 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
valid_keys->insert("rejectDupKeys");
valid_keys->insert("allowSpecialFloats");
}
bool CharReaderBuilder::validate(Json::Value* invalid) const
{
@@ -1947,8 +1980,10 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
(*settings)["allowSingleQuotes"] = false;
(*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
//! [CharReaderBuilderStrictMode]
}
// static
@@ -1964,6 +1999,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
(*settings)["stackLimit"] = 1000;
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
//! [CharReaderBuilderDefaults]
}
@@ -1993,7 +2029,7 @@ std::istream& operator>>(std::istream& sin, Value& root) {
"Error from reader: %s",
errs.c_str());
throwRuntimeError("reader error");
throwRuntimeError(errs);
}
return sin;
}

View File

@@ -30,8 +30,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
} else if (cp <= 0xFFFF) {
result.resize(3);
result[2] = static_cast<char>(0x80 | (0x3f & cp));
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
} else if (cp <= 0x10FFFF) {
result.resize(4);
result[3] = static_cast<char>(0x80 | (0x3f & cp));
@@ -43,7 +43,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
return result;
}
/// Returns true if ch is a control character (in range [0,32[).
/// Returns true if ch is a control character (in range [1,31]).
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
enum {
@@ -63,7 +63,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
static inline void uintToString(LargestUInt value, char*& current) {
*--current = 0;
do {
*--current = char(value % 10) + '0';
*--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
value /= 10;
} while (value != 0);
}

View File

@@ -4,9 +4,9 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
#include <jsoncpp/assertions.h>
#include <jsoncpp/value.h>
#include <jsoncpp/writer.h>
#include <json/assertions.h>
#include <json/value.h>
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <math.h>
#include <sstream>
@@ -55,6 +55,9 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
template <typename T, typename U>
static inline bool InRange(double d, T min, U max) {
// The casts can lose precision, but we are looking only for
// an approximate range. Might fail on edge cases though. ~cdunn
//return d >= static_cast<double>(min) && d <= static_cast<double>(max);
return d >= min && d <= max;
}
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
@@ -108,7 +111,7 @@ static inline char* duplicateAndPrefixStringValue(
JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
unsigned actualLength = length + sizeof(unsigned) + 1U;
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == 0) {
throwRuntimeError(
@@ -125,7 +128,7 @@ inline static void decodePrefixedString(
unsigned* length, char const** value)
{
if (!isPrefixed) {
*length = strlen(prefixed);
*length = static_cast<unsigned>(strlen(prefixed));
*value = prefixed;
} else {
*length = *reinterpret_cast<unsigned const*>(prefixed);
@@ -152,23 +155,6 @@ static inline void releaseStringValue(char* value) { free(value); }
namespace Json {
class JSON_API Exception : public std::exception {
public:
Exception(std::string const& msg);
virtual ~Exception() throw();
virtual char const* what() const throw();
protected:
std::string const msg_;
};
class JSON_API RuntimeError : public Exception {
public:
RuntimeError(std::string const& msg);
};
class JSON_API LogicError : public Exception {
public:
LogicError(std::string const& msg);
};
Exception::Exception(std::string const& msg)
: msg_(msg)
{}
@@ -232,28 +218,33 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
// Notes: policy_ indicates if the string was allocated when
// a string is stored.
Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate)
: cstr_(str)
{
Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
: cstr_(str) {
// allocate != duplicate
storage_.policy_ = allocate;
storage_.length_ = length;
storage_.policy_ = allocate & 0x3;
storage_.length_ = ulength & 0x3FFFFFFF;
}
Value::CZString::CZString(const CZString& other)
: cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
? duplicateStringValue(other.cstr_, other.storage_.length_)
: other.cstr_)
{
storage_.policy_ = (other.cstr_
? (other.storage_.policy_ == noDuplication
: other.cstr_) {
storage_.policy_ = static_cast<unsigned>(other.cstr_
? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
? noDuplication : duplicate)
: other.storage_.policy_);
: static_cast<DuplicationPolicy>(other.storage_.policy_));
storage_.length_ = other.storage_.length_;
}
#if JSON_HAS_RVALUE_REFERENCES
Value::CZString::CZString(CZString&& other)
: cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
}
#endif
Value::CZString::~CZString() {
if (cstr_ && storage_.policy_ == duplicate)
releaseStringValue(const_cast<char*>(cstr_));
@@ -312,9 +303,9 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
* memset( this, 0, sizeof(Value) )
* This optimization is used in ValueInternalMap fast allocator.
*/
Value::Value(ValueType type) {
initBasic(type);
switch (type) {
Value::Value(ValueType vtype) {
initBasic(vtype);
switch (vtype) {
case nullValue:
break;
case intValue:
@@ -442,6 +433,14 @@ Value::Value(Value const& other)
}
}
#if JSON_HAS_RVALUE_REFERENCES
// Move constructor
Value::Value(Value&& other) {
initBasic(nullValue);
swap(other);
}
#endif
Value::~Value() {
switch (type_) {
case nullValue:
@@ -478,7 +477,7 @@ void Value::swapPayload(Value& other) {
std::swap(value_, other.value_);
int temp2 = allocated_;
allocated_ = other.allocated_;
other.allocated_ = temp2;
other.allocated_ = temp2 & 0x1;
}
void Value::swap(Value& other) {
@@ -606,12 +605,12 @@ const char* Value::asCString() const {
return this_str;
}
bool Value::getString(char const** str, char const** end) const {
bool Value::getString(char const** str, char const** cend) const {
if (type_ != stringValue) return false;
if (value_.string_ == 0) return false;
unsigned length;
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
*end = *str + length;
*cend = *str + length;
return true;
}
@@ -785,7 +784,8 @@ float Value::asFloat() const {
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return static_cast<float>(value_.uint_);
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
return integerToDouble(value_.uint_);
// This can fail (silently?) if the value is bigger than MAX_FLOAT.
return static_cast<float>(integerToDouble(value_.uint_));
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
case realValue:
return static_cast<float>(value_.real_);
@@ -810,7 +810,8 @@ bool Value::asBool() const {
case uintValue:
return value_.uint_ ? true : false;
case realValue:
return value_.real_ ? true : false;
// This is kind of strange. Not recommended.
return (value_.real_ != 0.0) ? true : false;
default:
break;
}
@@ -960,8 +961,8 @@ const Value& Value::operator[](int index) const {
return (*this)[ArrayIndex(index)];
}
void Value::initBasic(ValueType type, bool allocated) {
type_ = type;
void Value::initBasic(ValueType vtype, bool allocated) {
type_ = vtype;
allocated_ = allocated;
comments_ = 0;
start_ = 0;
@@ -990,7 +991,7 @@ Value& Value::resolveReference(const char* key) {
}
// @param key is not null-terminated.
Value& Value::resolveReference(char const* key, char const* end)
Value& Value::resolveReference(char const* key, char const* cend)
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
@@ -998,7 +999,7 @@ Value& Value::resolveReference(char const* key, char const* end)
if (type_ == nullValue)
*this = Value(objectValue);
CZString actualKey(
key, static_cast<unsigned>(end-key), CZString::duplicateOnCopy);
key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
if (it != value_.map_->end() && (*it).first == actualKey)
return (*it).second;
@@ -1016,13 +1017,13 @@ Value Value::get(ArrayIndex index, const Value& defaultValue) const {
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
Value const* Value::find(char const* key, char const* end) const
Value const* Value::find(char const* key, char const* cend) const
{
JSON_ASSERT_MESSAGE(
type_ == nullValue || type_ == objectValue,
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
if (type_ == nullValue) return NULL;
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end()) return NULL;
return &(*it).second;
@@ -1066,9 +1067,9 @@ Value const& Value::operator[](CppTL::ConstString const& key) const
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
Value Value::get(char const* key, char const* end, Value const& defaultValue) const
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
{
Value const* found = find(key, end);
Value const* found = find(key, cend);
return !found ? defaultValue : *found;
}
Value Value::get(char const* key, Value const& defaultValue) const
@@ -1081,12 +1082,12 @@ Value Value::get(std::string const& key, Value const& defaultValue) const
}
bool Value::removeMember(const char* key, const char* end, Value* removed)
bool Value::removeMember(const char* key, const char* cend, Value* removed)
{
if (type_ != objectValue) {
return false;
}
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
@@ -1131,8 +1132,8 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
ArrayIndex oldSize = size();
// shift left all items left, into the place of the "removed"
for (ArrayIndex i = index; i < (oldSize - 1); ++i){
CZString key(i);
(*value_.map_)[key] = (*this)[i + 1];
CZString keey(i);
(*value_.map_)[keey] = (*this)[i + 1];
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
@@ -1148,9 +1149,9 @@ Value Value::get(const CppTL::ConstString& key,
}
#endif
bool Value::isMember(char const* key, char const* end) const
bool Value::isMember(char const* key, char const* cend) const
{
Value const* value = find(key, end);
Value const* value = find(key, cend);
return NULL != value;
}
bool Value::isMember(char const* key) const
@@ -1335,13 +1336,13 @@ std::string Value::getComment(CommentPlacement placement) const {
return "";
}
void Value::setOffsetStart(size_t start) { start_ = start; }
void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
size_t Value::getOffsetStart() const { return start_; }
ptrdiff_t Value::getOffsetStart() const { return start_; }
size_t Value::getOffsetLimit() const { return limit_; }
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
std::string Value::toStyledString() const {
StyledWriter writer;

View File

@@ -93,26 +93,26 @@ UInt ValueIteratorBase::index() const {
}
std::string ValueIteratorBase::name() const {
char const* key;
char const* keey;
char const* end;
key = memberName(&end);
if (!key) return std::string();
return std::string(key, end);
keey = memberName(&end);
if (!keey) return std::string();
return std::string(keey, end);
}
char const* ValueIteratorBase::memberName() const {
const char* name = (*current_).first.data();
return name ? name : "";
const char* cname = (*current_).first.data();
return cname ? cname : "";
}
char const* ValueIteratorBase::memberName(char const** end) const {
const char* name = (*current_).first.data();
if (!name) {
const char* cname = (*current_).first.data();
if (!cname) {
*end = NULL;
return NULL;
}
*end = name + (*current_).first.length();
return name;
*end = cname + (*current_).first.length();
return cname;
}
// //////////////////////////////////////////////////////////////////
@@ -129,6 +129,9 @@ ValueConstIterator::ValueConstIterator(
const Value::ObjectValues::iterator& current)
: ValueIteratorBase(current) {}
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
: ValueIteratorBase(other) {}
ValueConstIterator& ValueConstIterator::
operator=(const ValueIteratorBase& other) {
copy(other);
@@ -149,7 +152,9 @@ ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
: ValueIteratorBase(current) {}
ValueIterator::ValueIterator(const ValueConstIterator& other)
: ValueIteratorBase(other) {}
: ValueIteratorBase(other) {
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
}
ValueIterator::ValueIterator(const ValueIterator& other)
: ValueIteratorBase(other) {}

View File

@@ -4,7 +4,7 @@
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#if !defined(JSON_IS_AMALGAMATION)
#include <jsoncpp/writer.h>
#include <json/writer.h>
#include "json_tool.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <iomanip>
@@ -20,17 +20,52 @@
#include <float.h>
#define isfinite _finite
#elif defined(__sun) && defined(__SVR4) //Solaris
#if !defined(isfinite)
#include <ieeefp.h>
#define isfinite finite
#endif
#elif defined(_AIX)
#if !defined(isfinite)
#include <math.h>
#define isfinite finite
#endif
#elif defined(__hpux)
#if !defined(isfinite)
#if defined(__ia64) && !defined(finite)
#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
_Isfinitef(x) : _IsFinite(x)))
#else
#include <math.h>
#define isfinite finite
#endif
#endif
#else
#include <cmath>
#if !(defined(__QNXNTO__)) // QNX already defines isfinite
#define isfinite std::isfinite
#endif
#endif
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
#define snprintf _snprintf
#else
#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
#endif
#if defined(__BORLANDC__)
#include <float.h>
#define isfinite _finite
#define snprintf _snprintf
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
@@ -40,7 +75,7 @@
namespace Json {
#if __cplusplus >= 201103L
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
@@ -67,12 +102,15 @@ static bool containsControlCharacter0(const char* str, unsigned len) {
std::string valueToString(LargestInt value) {
UIntToStringBuffer buffer;
char* current = buffer + sizeof(buffer);
bool isNegative = value < 0;
if (isNegative)
value = -value;
uintToString(LargestUInt(value), current);
if (isNegative)
if (value == Value::minLargestInt) {
uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
*--current = '-';
} else if (value < 0) {
uintToString(LargestUInt(-value), current);
*--current = '-';
} else {
uintToString(LargestUInt(value), current);
}
assert(current >= buffer);
return current;
}
@@ -97,43 +135,38 @@ std::string valueToString(UInt value) {
#endif // # if defined(JSON_HAS_INT64)
std::string valueToString(double value) {
std::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[32];
int len = -1;
// Print into the buffer. We need not request the alternative representation
// that always has a decimal point because JSON doesn't distingish the
// concepts of reals and integers.
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with
// visual studio 2005 to
// avoid warning.
#if defined(WINCE)
len = _snprintf(buffer, sizeof(buffer), "%.17g", value);
#else
len = sprintf_s(buffer, sizeof(buffer), "%.17g", value);
#endif
#else
char formatString[6];
sprintf(formatString, "%%.%dg", precision);
// Print into the buffer. We need not request the alternative representation
// that always has a decimal point because JSON doesn't distingish the
// concepts of reals and integers.
if (isfinite(value)) {
len = snprintf(buffer, sizeof(buffer), "%.17g", value);
len = snprintf(buffer, sizeof(buffer), formatString, value);
} else {
// IEEE standard states that NaN values will not compare to themselves
if (value != value) {
len = snprintf(buffer, sizeof(buffer), "null");
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
} else if (value < 0) {
len = snprintf(buffer, sizeof(buffer), "-1e+9999");
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
} else {
len = snprintf(buffer, sizeof(buffer), "1e+9999");
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
}
// For those, we do not need to call fixNumLoc, but it is fast.
}
#endif
assert(len >= 0);
fixNumericLocale(buffer, buffer + len);
return buffer;
}
std::string valueToString(double value) { return valueToString(value, false, 17); }
std::string valueToString(bool value) { return value ? "true" : "false"; }
std::string valueToQuotedString(const char* value) {
@@ -317,15 +350,21 @@ void FastWriter::writeValue(const Value& value) {
document_ += valueToString(value.asDouble());
break;
case stringValue:
document_ += valueToQuotedString(value.asCString());
{
// Is NULL possible for value.string_?
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
break;
}
case booleanValue:
document_ += valueToString(value.asBool());
break;
case arrayValue: {
document_ += '[';
int size = value.size();
for (int index = 0; index < size; ++index) {
ArrayIndex size = value.size();
for (ArrayIndex index = 0; index < size; ++index) {
if (index > 0)
document_ += ',';
writeValue(value[index]);
@@ -340,7 +379,7 @@ void FastWriter::writeValue(const Value& value) {
const std::string& name = *it;
if (it != members.begin())
document_ += ',';
document_ += valueToQuotedStringN(name.data(), name.length());
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
writeValue(value[name]);
}
@@ -382,7 +421,7 @@ void StyledWriter::writeValue(const Value& value) {
break;
case stringValue:
{
// Is NULL is possible for value.string_?
// Is NULL possible for value.string_?
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
@@ -469,26 +508,25 @@ void StyledWriter::writeArrayValue(const Value& value) {
}
bool StyledWriter::isMultineArray(const Value& value) {
int size = value.size();
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (int index = 0; index < size && !isMultiLine; ++index) {
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine =
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (int index = 0; index < size; ++index) {
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
lineLength += int(childValues_[index].length());
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -522,7 +560,7 @@ void StyledWriter::writeWithIndent(const std::string& value) {
void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
void StyledWriter::unindent() {
assert(int(indentString_.size()) >= indentSize_);
assert(indentString_.size() >= indentSize_);
indentString_.resize(indentString_.size() - indentSize_);
}
@@ -599,8 +637,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
pushValue(valueToString(value.asDouble()));
break;
case stringValue:
pushValue(valueToQuotedString(value.asCString()));
{
// Is NULL possible for value.string_?
char const* str;
char const* end;
bool ok = value.getString(&str, &end);
if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
else pushValue("");
break;
}
case booleanValue:
pushValue(valueToString(value.asBool()));
break;
@@ -682,26 +727,25 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
}
bool StyledStreamWriter::isMultineArray(const Value& value) {
int size = value.size();
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (int index = 0; index < size && !isMultiLine; ++index) {
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
const Value& childValue = value[index];
isMultiLine =
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (int index = 0; index < size; ++index) {
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
lineLength += int(childValues_[index].length());
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -792,8 +836,10 @@ struct BuiltStyledStreamWriter : public StreamWriter
CommentStyle::Enum cs,
std::string const& colonSymbol,
std::string const& nullSymbol,
std::string const& endingLineFeedSymbol);
virtual int write(Value const& root, std::ostream* sout);
std::string const& endingLineFeedSymbol,
bool useSpecialFloats,
unsigned int precision);
int write(Value const& root, std::ostream* sout) override;
private:
void writeValue(Value const& value);
void writeArrayValue(Value const& value);
@@ -811,7 +857,7 @@ private:
ChildValues childValues_;
std::string indentString_;
int rightMargin_;
unsigned int rightMargin_;
std::string indentation_;
CommentStyle::Enum cs_;
std::string colonSymbol_;
@@ -819,13 +865,17 @@ private:
std::string endingLineFeedSymbol_;
bool addChildValues_ : 1;
bool indented_ : 1;
bool useSpecialFloats_ : 1;
unsigned int precision_;
};
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
std::string const& indentation,
CommentStyle::Enum cs,
std::string const& colonSymbol,
std::string const& nullSymbol,
std::string const& endingLineFeedSymbol)
std::string const& endingLineFeedSymbol,
bool useSpecialFloats,
unsigned int precision)
: rightMargin_(74)
, indentation_(indentation)
, cs_(cs)
@@ -834,6 +884,8 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
, endingLineFeedSymbol_(endingLineFeedSymbol)
, addChildValues_(false)
, indented_(false)
, useSpecialFloats_(useSpecialFloats)
, precision_(precision)
{
}
int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
@@ -863,7 +915,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
pushValue(valueToString(value.asLargestUInt()));
break;
case realValue:
pushValue(valueToString(value.asDouble()));
pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
break;
case stringValue:
{
@@ -893,7 +945,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
std::string const& name = *it;
Value const& childValue = value[name];
writeCommentBeforeValue(childValue);
writeWithIndent(valueToQuotedStringN(name.data(), name.length()));
writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
*sout_ << colonSymbol_;
writeValue(childValue);
if (++it == members.end()) {
@@ -958,26 +1010,25 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
}
bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
int size = value.size();
ArrayIndex const size = value.size();
bool isMultiLine = size * 3 >= rightMargin_;
childValues_.clear();
for (int index = 0; index < size && !isMultiLine; ++index) {
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
Value const& childValue = value[index];
isMultiLine =
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
childValue.size() > 0);
}
if (!isMultiLine) // check if line length > max line length
{
childValues_.reserve(size);
addChildValues_ = true;
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (int index = 0; index < size; ++index) {
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
for (ArrayIndex index = 0; index < size; ++index) {
if (hasCommentForValue(value[index])) {
isMultiLine = true;
}
writeValue(value[index]);
lineLength += int(childValues_[index].length());
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
}
addChildValues_ = false;
isMultiLine = isMultiLine || lineLength >= rightMargin_;
@@ -1078,6 +1129,8 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
std::string cs_str = settings_["commentStyle"].asString();
bool eyc = settings_["enableYAMLCompatibility"].asBool();
bool dnp = settings_["dropNullPlaceholders"].asBool();
bool usf = settings_["useSpecialFloats"].asBool();
unsigned int pre = settings_["precision"].asUInt();
CommentStyle::Enum cs = CommentStyle::All;
if (cs_str == "All") {
cs = CommentStyle::All;
@@ -1096,10 +1149,11 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const
if (dnp) {
nullSymbol = "";
}
if (pre > 17) pre = 17;
std::string endingLineFeedSymbol = "";
return new BuiltStyledStreamWriter(
indentation, cs,
colonSymbol, nullSymbol, endingLineFeedSymbol);
colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
}
static void getValidWriterKeys(std::set<std::string>* valid_keys)
{
@@ -1108,6 +1162,8 @@ static void getValidWriterKeys(std::set<std::string>* valid_keys)
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
{
@@ -1138,6 +1194,8 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
(*settings)["indentation"] = "\t";
(*settings)["enableYAMLCompatibility"] = false;
(*settings)["dropNullPlaceholders"] = false;
(*settings)["useSpecialFloats"] = false;
(*settings)["precision"] = 17;
//! [StreamWriterBuilderDefaults]
}

View File

@@ -1,5 +1,4 @@
// DO NOT EDIT. This file is generated by CMake from "version"
// and "version.h.in" files.
// DO NOT EDIT. This file (and "version") is generated by CMake.
// Run CMake configure step to update it.
#ifndef JSON_VERSION_H_INCLUDED
# define JSON_VERSION_H_INCLUDED

View File

@@ -1,9 +1,5 @@
# vim: et ts=4 sts=4 sw=4 tw=0
IF(JSONCPP_LIB_BUILD_SHARED)
ADD_DEFINITIONS( -DJSON_DLL )
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ADD_EXECUTABLE( jsoncpp_test
jsontest.cpp
jsontest.h
@@ -11,11 +7,12 @@ ADD_EXECUTABLE( jsoncpp_test
)
IF(JSONCPP_LIB_BUILD_SHARED)
IF(BUILD_SHARED_LIBS)
ADD_DEFINITIONS( -DJSON_DLL )
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib)
ELSE(JSONCPP_LIB_BUILD_SHARED)
ELSE(BUILD_SHARED_LIBS)
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib_static)
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ENDIF()
# another way to solve issue #90
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
@@ -23,19 +20,19 @@ ENDIF(JSONCPP_LIB_BUILD_SHARED)
# Run unit tests in post-build
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
IF(JSONCPP_WITH_POST_BUILD_UNITTEST)
IF(JSONCPP_LIB_BUILD_SHARED)
IF(BUILD_SHARED_LIBS)
# First, copy the shared lib, for Microsoft.
# Then, run the test executable.
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:jsoncpp_lib> $<TARGET_FILE_DIR:jsoncpp_test>
COMMAND $<TARGET_FILE:jsoncpp_test>)
ELSE(JSONCPP_LIB_BUILD_SHARED)
ELSE(BUILD_SHARED_LIBS)
# Just run the test executable.
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
POST_BUILD
COMMAND $<TARGET_FILE:jsoncpp_test>)
ENDIF(JSONCPP_LIB_BUILD_SHARED)
ENDIF(JSONCPP_WITH_POST_BUILD_UNITTEST)
ENDIF()
ENDIF()
SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)

View File

@@ -265,8 +265,8 @@ TestResult& checkStringEqual(TestResult& result,
} \
\
public: /* overidden from TestCase */ \
virtual const char* testName() const { return #FixtureType "/" #name; } \
virtual void runTestCase(); \
const char* testName() const override { return #FixtureType "/" #name; } \
void runTestCase() override; \
}; \
\
void Test##FixtureType##name::runTestCase()

View File

@@ -7,6 +7,10 @@
#include <json/config.h>
#include <json/json.h>
#include <cstring>
#include <limits>
#include <sstream>
#include <string>
#include <iomanip>
// Make numeric limits more convenient to talk about.
// Assumes int type in 32 bits.
@@ -257,6 +261,20 @@ JSONTEST_FIXTURE(ValueTest, arrays) {
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
}
JSONTEST_FIXTURE(ValueTest, arrayIssue252)
{
int count = 5;
Json::Value root;
Json::Value item;
root["array"] = Json::Value::nullRef;
for (int i = 0; i < count; i++)
{
item["a"] = i;
item["b"] = i;
root["array"][i] = item;
}
//JSONTEST_ASSERT_EQUAL(5, root["array"].size());
}
JSONTEST_FIXTURE(ValueTest, null) {
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());
@@ -1198,7 +1216,7 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble());
JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat());
#ifdef JSON_HAS_INT64
JSONTEST_ASSERT_EQUAL(-Json::Int64(1) << 31, val.asLargestInt());
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 31), val.asLargestInt());
#endif
JSONTEST_ASSERT_EQUAL(true, val.asBool());
JSONTEST_ASSERT_EQUAL("-2147483648.5",
@@ -1240,7 +1258,7 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
// A 16-digit floating point number.
val = Json::Value(2199023255552000.0f);
JSONTEST_ASSERT_EQUAL(float(2199023255552000), val.asFloat());
JSONTEST_ASSERT_EQUAL(float(2199023255552000.0f), val.asFloat());
JSONTEST_ASSERT_STRING_EQUAL("2199023255552000",
normalizeFloatingPointStr(val.asString()));
@@ -1542,7 +1560,7 @@ JSONTEST_FIXTURE(ValueTest, StaticString) {
JSONTEST_FIXTURE(ValueTest, CommentBefore) {
Json::Value val; // fill val
val.setComment("// this comment should appear before", Json::commentBefore);
val.setComment(std::string("// this comment should appear before"), Json::commentBefore);
Json::StreamWriterBuilder wbuilder;
wbuilder.settings_["commentStyle"] = "All";
{
@@ -1637,6 +1655,63 @@ JSONTEST_FIXTURE(ValueTest, zeroesInKeys) {
}
}
JSONTEST_FIXTURE(ValueTest, specialFloats) {
Json::StreamWriterBuilder b;
b.settings_["useSpecialFloats"] = true;
Json::Value v = std::numeric_limits<double>::quiet_NaN();
std::string expected = "NaN";
std::string result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = std::numeric_limits<double>::infinity();
expected = "Infinity";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = -std::numeric_limits<double>::infinity();
expected = "-Infinity";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
JSONTEST_FIXTURE(ValueTest, precision) {
Json::StreamWriterBuilder b;
b.settings_["precision"] = 5;
Json::Value v = 100.0/3;
std::string expected = "33.333";
std::string result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = 0.25000000;
expected = "0.25";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
v = 0.2563456;
expected = "0.25635";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 1;
expected = "0.3";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 17;
v = 1234857476305.256345694873740545068;
expected = "1234857476305.2563";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
b.settings_["precision"] = 24;
v = 0.256345694873740545068;
expected = "0.25634569487374054";
result = Json::writeString(b, v);
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
}
struct WriterTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) {
@@ -1910,7 +1985,7 @@ JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) {
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
// This is interpretted as a string value followed by a colon.
// This is interpreted as a string value followed by a colon.
Json::CharReaderBuilder b;
Json::Value root;
char const doc[] =
@@ -2209,6 +2284,7 @@ JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) {
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
}
delete reader;
}
struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
@@ -2241,6 +2317,82 @@ JSONTEST_FIXTURE(CharReaderAllowZeroesTest, issue176) {
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
}
delete reader;
}
struct CharReaderAllowSpecialFloatsTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(CharReaderAllowSpecialFloatsTest, issue209) {
Json::CharReaderBuilder b;
b.settings_["allowSpecialFloats"] = true;
Json::Value root;
std::string errs;
Json::CharReader* reader(b.newCharReader());
{
char const doc[] = "{\"a\":NaN,\"b\":Infinity,\"c\":-Infinity}";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(3u, root.size());
double n = root["a"].asDouble();
JSONTEST_ASSERT(n != n);
JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), root.get("b", 0.0));
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(), root.get("c", 0.0));
}
struct TestData {
int line;
bool ok;
std::string in;
};
const TestData test_data[] = {
{__LINE__, 1, "{\"a\":9}"},
{__LINE__, 0, "{\"a\":0Infinity}"},
{__LINE__, 0, "{\"a\":1Infinity}"},
{__LINE__, 0, "{\"a\":9Infinity}"},
{__LINE__, 0, "{\"a\":0nfinity}"},
{__LINE__, 0, "{\"a\":1nfinity}"},
{__LINE__, 0, "{\"a\":9nfinity}"},
{__LINE__, 0, "{\"a\":nfinity}"},
{__LINE__, 0, "{\"a\":.nfinity}"},
{__LINE__, 0, "{\"a\":9nfinity}"},
{__LINE__, 0, "{\"a\":-nfinity}"},
{__LINE__, 1, "{\"a\":Infinity}"},
{__LINE__, 0, "{\"a\":.Infinity}"},
{__LINE__, 0, "{\"a\":_Infinity}"},
{__LINE__, 0, "{\"a\":_nfinity}"},
{__LINE__, 1, "{\"a\":-Infinity}"}
};
for (size_t tdi = 0; tdi < sizeof(test_data) / sizeof(*test_data); ++tdi) {
const TestData& td = test_data[tdi];
bool ok = reader->parse(&*td.in.begin(),
&*td.in.begin() + td.in.size(),
&root, &errs);
JSONTEST_ASSERT(td.ok == ok)
<< "line:" << td.line << "\n"
<< " expected: {"
<< "ok:" << td.ok
<< ", in:\'" << td.in << "\'"
<< "}\n"
<< " actual: {"
<< "ok:" << ok
<< "}\n";
}
{
char const doc[] = "{\"posInf\": Infinity, \"NegInf\": -Infinity}";
bool ok = reader->parse(
doc, doc + std::strlen(doc),
&root, &errs);
JSONTEST_ASSERT(ok);
JSONTEST_ASSERT_STRING_EQUAL("", errs);
JSONTEST_ASSERT_EQUAL(2u, root.size());
JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), root["posInf"].asDouble());
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(), root["NegInf"].asDouble());
}
delete reader;
}
struct BuilderTest : JsonTest::TestCase {};
@@ -2318,12 +2470,53 @@ JSONTEST_FIXTURE(IteratorTest, indexes) {
JSONTEST_ASSERT(it == json.end());
}
JSONTEST_FIXTURE(IteratorTest, const) {
Json::Value const v;
JSONTEST_ASSERT_THROWS(
Json::Value::iterator it(v.begin()) // Compile, but throw.
);
Json::Value value;
for(int i = 9; i < 12; ++i)
{
std::ostringstream out;
out << std::setw(2) << i;
std::string str = out.str();
value[str] = str;
}
std::ostringstream out;
//in old code, this will get a compile error
Json::Value::const_iterator iter = value.begin();
for(; iter != value.end(); ++iter)
{
out << *iter << ',';
}
std::string expected = "\" 9\",\"10\",\"11\",";
JSONTEST_ASSERT_STRING_EQUAL(expected, out.str());
}
struct RValueTest : JsonTest::TestCase {};
JSONTEST_FIXTURE(RValueTest, moveConstruction) {
#if JSON_HAS_RVALUE_REFERENCES
Json::Value json;
json["key"] = "value";
Json::Value moved = std::move(json);
JSONTEST_ASSERT(moved != json); // Possibly not nullValue; definitely not equal.
JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type());
JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type());
#endif
}
int main(int argc, const char* argv[]) {
JsonTest::Runner runner;
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayIssue252);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools);
@@ -2345,6 +2538,8 @@ int main(int argc, const char* argv[]) {
//JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nulls);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, specialFloats);
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, precision);
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
@@ -2379,11 +2574,16 @@ int main(int argc, const char* argv[]) {
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowZeroesTest, issue176);
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSpecialFloatsTest, issue209);
JSONTEST_REGISTER_FIXTURE(runner, BuilderTest, settings);
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, names);
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, indexes);
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, const);
JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction);
return runner.runCommandLine(argc, argv);
}