mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 23:20:05 +02:00
Compare commits
40 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
4ce4bb8404 | ||
![]() |
2cd0f4ec21 | ||
![]() |
836f0fb863 | ||
![]() |
37644abd77 | ||
![]() |
66eb72f121 | ||
![]() |
94b0297dc5 | ||
![]() |
55db3c3cb2 | ||
![]() |
c07ef37904 | ||
![]() |
62ab94ddd3 | ||
![]() |
09d352ac13 | ||
![]() |
50753bb808 | ||
![]() |
8f3aa220db | ||
![]() |
73e127892e | ||
![]() |
4997dfb8af | ||
![]() |
c1441ef5e0 | ||
![]() |
e0bfb45000 | ||
![]() |
4bc311503c | ||
![]() |
cd140b5141 | ||
![]() |
01aee4a0dc | ||
![]() |
59a01652ab | ||
![]() |
8371a4337c | ||
![]() |
dc2e1c98b9 | ||
![]() |
d98b5f4230 | ||
![]() |
4ca9d25ccc | ||
![]() |
6eaf150dc7 | ||
![]() |
8b489f891a | ||
![]() |
65cee6ea16 | ||
![]() |
dfc5f879c1 | ||
![]() |
1a4dc3a888 | ||
![]() |
0f6884f771 | ||
![]() |
748328a0d1 | ||
![]() |
f44278cd4e | ||
![]() |
d2b6992f3e | ||
![]() |
54764dd85b | ||
![]() |
8dd32e1e2e | ||
![]() |
3fd7f8b470 | ||
![]() |
e99e6d9cc6 | ||
![]() |
9ca1aaab14 | ||
![]() |
27639ce578 | ||
![]() |
f8a3a599ac |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -10,4 +10,4 @@
|
||||
/libs/
|
||||
/doc/doxyfile
|
||||
/dist/
|
||||
/include/json/version.h
|
||||
#/include/json/version.h
|
||||
|
@@ -17,28 +17,20 @@ IF(NOT WIN32)
|
||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
||||
ENDIF(NOT WIN32)
|
||||
|
||||
SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory")
|
||||
|
||||
SET(RUNTIME_INSTALL_DIR bin
|
||||
CACHE PATH "Install dir for executables and dlls")
|
||||
SET(ARCHIVE_INSTALL_DIR lib
|
||||
SET(ARCHIVE_INSTALL_DIR lib${LIB_SUFFIX}
|
||||
CACHE PATH "Install dir for static libraries")
|
||||
SET(LIBRARY_INSTALL_DIR lib
|
||||
SET(LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}
|
||||
CACHE PATH "Install dir for shared libraries")
|
||||
SET(INCLUDE_INSTALL_DIR include
|
||||
CACHE PATH "Install dir for headers")
|
||||
SET(PACKAGE_INSTALL_DIR lib/cmake
|
||||
SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake
|
||||
CACHE PATH "Install dir for cmake package config files")
|
||||
MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR )
|
||||
|
||||
# This ensures shared DLL are in the same dir as executable on Windows.
|
||||
# Put all executables / libraries are in a project global directory.
|
||||
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
|
||||
CACHE PATH "Single directory for all static libraries.")
|
||||
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib
|
||||
CACHE PATH "Single directory for all dynamic libraries on Unix.")
|
||||
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin
|
||||
CACHE PATH "Single directory for all executable and dynamic libraries on Windows.")
|
||||
MARK_AS_ADVANCED( CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_ARCHIVE_OUTPUT_DIRECTORY )
|
||||
|
||||
# Set variable named ${VAR_NAME} to value ${VALUE}
|
||||
FUNCTION(set_using_dynamic_name VAR_NAME VALUE)
|
||||
SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
|
||||
@@ -101,7 +93,7 @@ IF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||
"pkg-config/jsoncpp.pc"
|
||||
@ONLY)
|
||||
INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc"
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig")
|
||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig")
|
||||
ENDIF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||
|
||||
IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
|
@@ -187,7 +187,6 @@ private:
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
|
||||
bool expectToken(TokenType type, Token& token, const char* message);
|
||||
bool readToken(Token& token);
|
||||
void skipSpaces();
|
||||
bool match(Location pattern, int patternLength);
|
||||
|
@@ -235,25 +235,26 @@ Json::Value obj_value(Json::objectValue); // {}
|
||||
Value(const CppTL::ConstString& value);
|
||||
#endif
|
||||
Value(bool value);
|
||||
/// Deep copy.
|
||||
Value(const Value& other);
|
||||
~Value();
|
||||
|
||||
// Deep copy, then swap(other).
|
||||
Value& operator=(Value other);
|
||||
/// Swap values.
|
||||
/// \note Currently, comments are intentionally not swapped, for
|
||||
/// both logic and efficiency.
|
||||
/// Swap everything.
|
||||
void swap(Value& other);
|
||||
/// Swap values but leave comments and source offsets in place.
|
||||
void swapPayload(Value& other);
|
||||
|
||||
ValueType type() const;
|
||||
|
||||
/// Compare payload only, not comments etc.
|
||||
bool operator<(const Value& other) const;
|
||||
bool operator<=(const Value& other) const;
|
||||
bool operator>=(const Value& other) const;
|
||||
bool operator>(const Value& other) const;
|
||||
|
||||
bool operator==(const Value& other) const;
|
||||
bool operator!=(const Value& other) const;
|
||||
|
||||
int compare(const Value& other) const;
|
||||
|
||||
const char* asCString() const;
|
||||
|
@@ -4,9 +4,9 @@
|
||||
#ifndef JSON_VERSION_H_INCLUDED
|
||||
# define JSON_VERSION_H_INCLUDED
|
||||
|
||||
# define JSONCPP_VERSION_STRING "1.0.0"
|
||||
# define JSONCPP_VERSION_STRING "1.2.0"
|
||||
# define JSONCPP_VERSION_MAJOR 1
|
||||
# define JSONCPP_VERSION_MINOR 0
|
||||
# define JSONCPP_VERSION_MINOR 2
|
||||
# define JSONCPP_VERSION_PATCH 0
|
||||
# define JSONCPP_VERSION_QUALIFIER
|
||||
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=${prefix}
|
||||
libdir=${exec_prefix}/lib
|
||||
libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@
|
||||
includedir=${prefix}/@INCLUDE_INSTALL_DIR@
|
||||
|
||||
Name: jsoncpp
|
||||
|
@@ -1,4 +1,8 @@
|
||||
OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF)
|
||||
IF(BUILD_SHARED_LIBS)
|
||||
SET(JSONCPP_LIB_BUILD_SHARED ON)
|
||||
ENDIF(BUILD_SHARED_LIBS)
|
||||
|
||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
||||
SET(JSONCPP_LIB_TYPE SHARED)
|
||||
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
|
||||
@@ -6,9 +10,15 @@ ELSE(JSONCPP_LIB_BUILD_SHARED)
|
||||
SET(JSONCPP_LIB_TYPE STATIC)
|
||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
||||
|
||||
|
||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
||||
#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")
|
||||
endif()
|
||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
||||
|
||||
SET( JSONCPP_INCLUDE_DIR ../../include )
|
||||
@@ -39,12 +49,15 @@ ADD_LIBRARY( jsoncpp_lib ${JSONCPP_LIB_TYPE}
|
||||
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
|
||||
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR} )
|
||||
|
||||
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
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)
|
||||
|
||||
# Install instructions for this target
|
||||
IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib
|
||||
PUBLIC $<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSON_INCLUDE_DIR}>
|
||||
)
|
||||
SET(INSTALL_EXPORT EXPORT jsoncpp)
|
||||
ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
SET(INSTALL_EXPORT)
|
||||
|
@@ -47,23 +47,6 @@ Features Features::strictMode() {
|
||||
// Implementation of class Reader
|
||||
// ////////////////////////////////
|
||||
|
||||
static inline bool in(Reader::Char c,
|
||||
Reader::Char c1,
|
||||
Reader::Char c2,
|
||||
Reader::Char c3,
|
||||
Reader::Char c4) {
|
||||
return c == c1 || c == c2 || c == c3 || c == c4;
|
||||
}
|
||||
|
||||
static inline bool in(Reader::Char c,
|
||||
Reader::Char c1,
|
||||
Reader::Char c2,
|
||||
Reader::Char c3,
|
||||
Reader::Char c4,
|
||||
Reader::Char c5) {
|
||||
return c == c1 || c == c2 || c == c3 || c == c4 || c == c5;
|
||||
}
|
||||
|
||||
static bool containsNewLine(Reader::Location begin, Reader::Location end) {
|
||||
for (; begin < end; ++begin)
|
||||
if (*begin == '\n' || *begin == '\r')
|
||||
@@ -180,26 +163,36 @@ bool Reader::readValue() {
|
||||
successful = decodeString(token);
|
||||
break;
|
||||
case tokenTrue:
|
||||
currentValue() = true;
|
||||
{
|
||||
Value v(true);
|
||||
currentValue().swapPayload(v);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
}
|
||||
break;
|
||||
case tokenFalse:
|
||||
currentValue() = false;
|
||||
{
|
||||
Value v(false);
|
||||
currentValue().swapPayload(v);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
}
|
||||
break;
|
||||
case tokenNull:
|
||||
currentValue() = Value();
|
||||
{
|
||||
Value v;
|
||||
currentValue().swapPayload(v);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
}
|
||||
break;
|
||||
case tokenArraySeparator:
|
||||
if (features_.allowDroppedNullPlaceholders_) {
|
||||
// "Un-read" the current token and mark the current value as a null
|
||||
// token.
|
||||
current_--;
|
||||
currentValue() = Value();
|
||||
Value v;
|
||||
currentValue().swapPayload(v);
|
||||
currentValue().setOffsetStart(current_ - begin_ - 1);
|
||||
currentValue().setOffsetLimit(current_ - begin_);
|
||||
break;
|
||||
@@ -229,13 +222,6 @@ void Reader::skipCommentTokens(Token& token) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Reader::expectToken(TokenType type, Token& token, const char* message) {
|
||||
readToken(token);
|
||||
if (token.type_ != type)
|
||||
return addError(message, token);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Reader::readToken(Token& token) {
|
||||
skipSpaces();
|
||||
token.start_ = current_;
|
||||
@@ -381,11 +367,24 @@ bool Reader::readCppStyleComment() {
|
||||
}
|
||||
|
||||
void Reader::readNumber() {
|
||||
while (current_ != end_) {
|
||||
if (!(*current_ >= '0' && *current_ <= '9') &&
|
||||
!in(*current_, '.', 'e', 'E', '+', '-'))
|
||||
break;
|
||||
++current_;
|
||||
const char *p = current_;
|
||||
char c = '0'; // stopgap for already consumed character
|
||||
// integral part
|
||||
while (c >= '0' && c <= '9')
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
// fractional part
|
||||
if (c == '.') {
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
while (c >= '0' && c <= '9')
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
}
|
||||
// exponential part
|
||||
if (c == 'e' || c == 'E') {
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
if (c == '+' || c == '-')
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
while (c >= '0' && c <= '9')
|
||||
c = (current_ = p) < end_ ? *p++ : 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +403,8 @@ bool Reader::readString() {
|
||||
bool Reader::readObject(Token& tokenStart) {
|
||||
Token tokenName;
|
||||
std::string name;
|
||||
currentValue() = Value(objectValue);
|
||||
Value init(objectValue);
|
||||
currentValue().swapPayload(init);
|
||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||
while (readToken(tokenName)) {
|
||||
bool initialTokenOk = true;
|
||||
@@ -457,7 +457,8 @@ bool Reader::readObject(Token& tokenStart) {
|
||||
}
|
||||
|
||||
bool Reader::readArray(Token& tokenStart) {
|
||||
currentValue() = Value(arrayValue);
|
||||
Value init(arrayValue);
|
||||
currentValue().swapPayload(init);
|
||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||
skipSpaces();
|
||||
if (*current_ == ']') // empty array
|
||||
@@ -497,20 +498,13 @@ bool Reader::decodeNumber(Token& token) {
|
||||
Value decoded;
|
||||
if (!decodeNumber(token, decoded))
|
||||
return false;
|
||||
currentValue() = decoded;
|
||||
currentValue().swapPayload(decoded);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Reader::decodeNumber(Token& token, Value& decoded) {
|
||||
bool isDouble = false;
|
||||
for (Location inspect = token.start_; inspect != token.end_; ++inspect) {
|
||||
isDouble = isDouble || in(*inspect, '.', 'e', 'E', '+') ||
|
||||
(*inspect == '-' && inspect != token.start_);
|
||||
}
|
||||
if (isDouble)
|
||||
return decodeDouble(token, decoded);
|
||||
// Attempts to parse the number as an integer. If the number is
|
||||
// larger than the maximum supported value of an integer then
|
||||
// we decode the number as a double.
|
||||
@@ -518,6 +512,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
||||
bool isNegative = *current == '-';
|
||||
if (isNegative)
|
||||
++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)
|
||||
: Value::maxLargestUInt;
|
||||
@@ -526,9 +521,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
||||
while (current < token.end_) {
|
||||
Char c = *current++;
|
||||
if (c < '0' || c > '9')
|
||||
return addError("'" + std::string(token.start_, token.end_) +
|
||||
"' is not a number.",
|
||||
token);
|
||||
return decodeDouble(token, decoded);
|
||||
Value::UInt digit(c - '0');
|
||||
if (value >= threshold) {
|
||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||
@@ -555,7 +548,7 @@ bool Reader::decodeDouble(Token& token) {
|
||||
Value decoded;
|
||||
if (!decodeDouble(token, decoded))
|
||||
return false;
|
||||
currentValue() = decoded;
|
||||
currentValue().swapPayload(decoded);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
return true;
|
||||
@@ -598,10 +591,11 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
|
||||
}
|
||||
|
||||
bool Reader::decodeString(Token& token) {
|
||||
std::string decoded;
|
||||
if (!decodeString(token, decoded))
|
||||
std::string decoded_string;
|
||||
if (!decodeString(token, decoded_string))
|
||||
return false;
|
||||
currentValue() = decoded;
|
||||
Value decoded(decoded_string);
|
||||
currentValue().swapPayload(decoded);
|
||||
currentValue().setOffsetStart(token.start_ - begin_);
|
||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||
return true;
|
||||
|
@@ -410,7 +410,7 @@ Value& Value::operator=(Value other) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
void Value::swap(Value& other) {
|
||||
void Value::swapPayload(Value& other) {
|
||||
ValueType temp = type_;
|
||||
type_ = other.type_;
|
||||
other.type_ = temp;
|
||||
@@ -418,6 +418,11 @@ void Value::swap(Value& other) {
|
||||
int temp2 = allocated_;
|
||||
allocated_ = other.allocated_;
|
||||
other.allocated_ = temp2;
|
||||
}
|
||||
|
||||
void Value::swap(Value& other) {
|
||||
swapPayload(other);
|
||||
std::swap(comments_, other.comments_);
|
||||
std::swap(start_, other.start_);
|
||||
std::swap(limit_, other.limit_);
|
||||
}
|
||||
|
@@ -26,6 +26,11 @@
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
#if defined(__sun) && defined(__SVR4) //Solaris
|
||||
#include <ieeefp.h>
|
||||
#define isfinite finite
|
||||
#endif
|
||||
|
||||
namespace Json {
|
||||
|
||||
static bool containsControlCharacter(const char* str) {
|
||||
@@ -82,13 +87,13 @@ std::string valueToString(double value) {
|
||||
// visual studio 2005 to
|
||||
// avoid warning.
|
||||
#if defined(WINCE)
|
||||
len = _snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||
len = _snprintf(buffer, sizeof(buffer), "%.17g", value);
|
||||
#else
|
||||
len = sprintf_s(buffer, sizeof(buffer), "%.16g", value);
|
||||
len = sprintf_s(buffer, sizeof(buffer), "%.17g", value);
|
||||
#endif
|
||||
#else
|
||||
if (isfinite(value)) {
|
||||
len = snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||
len = snprintf(buffer, sizeof(buffer), "%.17g", value);
|
||||
} else {
|
||||
// IEEE standard states that NaN values will not compare to themselves
|
||||
if (value != value) {
|
||||
|
@@ -926,7 +926,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
||||
JSONTEST_ASSERT_EQUAL(float(uint64ToDouble(Json::UInt64(1) << 63)),
|
||||
val.asFloat());
|
||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||
JSONTEST_ASSERT_STRING_EQUAL("9.223372036854776e+18",
|
||||
JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18",
|
||||
normalizeFloatingPointStr(val.asString()));
|
||||
|
||||
// int64 min
|
||||
@@ -974,7 +974,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
||||
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asDouble());
|
||||
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
|
||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||
JSONTEST_ASSERT_STRING_EQUAL("-9.223372036854776e+18",
|
||||
JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18",
|
||||
normalizeFloatingPointStr(val.asString()));
|
||||
|
||||
// 10^19
|
||||
@@ -1065,7 +1065,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
||||
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asDouble());
|
||||
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
|
||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||
JSONTEST_ASSERT_STRING_EQUAL("1.844674407370955e+19",
|
||||
JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19",
|
||||
normalizeFloatingPointStr(val.asString()));
|
||||
#endif
|
||||
}
|
||||
@@ -1217,7 +1217,7 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
|
||||
normalizeFloatingPointStr(val.asString()));
|
||||
|
||||
val = Json::Value(1.2345678901234);
|
||||
JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234",
|
||||
JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001",
|
||||
normalizeFloatingPointStr(val.asString()));
|
||||
|
||||
// A 16-digit floating point number.
|
||||
|
@@ -1,4 +1,5 @@
|
||||
.={}
|
||||
// Comment for array
|
||||
.test=[]
|
||||
.test[0]={}
|
||||
.test[0].a="aaa"
|
||||
|
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"test":
|
||||
// Comment for array
|
||||
[
|
||||
{ "a" : "aaa" }, // Comment for a
|
||||
{ "b" : "bbb" }, // Comment for b
|
||||
|
@@ -11,4 +11,13 @@
|
||||
// Multiline comment cpp-style
|
||||
// Second line
|
||||
.cpp-test.c=3
|
||||
.cpp-test.d=4
|
||||
// Comment before double
|
||||
.cpp-test.d=4.1
|
||||
// Comment before string
|
||||
.cpp-test.e="e-string"
|
||||
// Comment before true
|
||||
.cpp-test.f=true
|
||||
// Comment before false
|
||||
.cpp-test.g=false
|
||||
// Comment before null
|
||||
.cpp-test.h=null
|
||||
|
@@ -12,6 +12,15 @@
|
||||
// Multiline comment cpp-style
|
||||
// Second line
|
||||
"c" : 3,
|
||||
"d" : 4
|
||||
// Comment before double
|
||||
"d" : 4.1,
|
||||
// Comment before string
|
||||
"e" : "e-string",
|
||||
// Comment before true
|
||||
"f" : true,
|
||||
// Comment before false
|
||||
"g" : false,
|
||||
// Comment before null
|
||||
"h" : null
|
||||
}
|
||||
}
|
||||
|
@@ -1,12 +1,30 @@
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from io import open
|
||||
from glob import glob
|
||||
import sys
|
||||
import os
|
||||
import os.path
|
||||
from glob import glob
|
||||
import optparse
|
||||
|
||||
VALGRIND_CMD = 'valgrind --tool=memcheck --leak-check=yes --undef-value-errors=yes '
|
||||
|
||||
def getStatusOutput(cmd):
|
||||
"""
|
||||
Return int, unicode (for both Python 2 and 3).
|
||||
Note: os.popen().close() would return None for 0.
|
||||
"""
|
||||
pipe = os.popen(cmd)
|
||||
process_output = pipe.read()
|
||||
try:
|
||||
# We have been using os.popen(). When we read() the result
|
||||
# we get 'str' (bytes) in py2, and 'str' (unicode) in py3.
|
||||
# Ugh! There must be a better way to handle this.
|
||||
process_output = process_output.decode('utf-8')
|
||||
except AttributeError:
|
||||
pass # python3
|
||||
status = pipe.close()
|
||||
return status, process_output
|
||||
def compareOutputs( expected, actual, message ):
|
||||
expected = expected.strip().replace('\r','').split('\n')
|
||||
actual = actual.strip().replace('\r','').split('\n')
|
||||
@@ -34,7 +52,7 @@ def compareOutputs( expected, actual, message ):
|
||||
|
||||
def safeReadFile( path ):
|
||||
try:
|
||||
return file( path, 'rt' ).read()
|
||||
return open( path, 'rt', encoding = 'utf-8' ).read()
|
||||
except IOError as e:
|
||||
return '<File "%s" is missing: %s>' % (path,e)
|
||||
|
||||
@@ -54,21 +72,20 @@ def runAllTests( jsontest_executable_path, input_dir = None,
|
||||
is_json_checker_test = (input_path in test_jsonchecker) or expect_failure
|
||||
print('TESTING:', input_path, end=' ')
|
||||
options = is_json_checker_test and '--json-checker' or ''
|
||||
pipe = os.popen( "%s%s %s %s" % (
|
||||
cmd = '%s%s %s "%s"' % (
|
||||
valgrind_path, jsontest_executable_path, options,
|
||||
input_path) )
|
||||
process_output = pipe.read()
|
||||
status = pipe.close()
|
||||
input_path)
|
||||
status, process_output = getStatusOutput(cmd)
|
||||
if is_json_checker_test:
|
||||
if expect_failure:
|
||||
if status is None:
|
||||
if not status:
|
||||
print('FAILED')
|
||||
failed_tests.append( (input_path, 'Parsing should have failed:\n%s' %
|
||||
safeReadFile(input_path)) )
|
||||
else:
|
||||
print('OK')
|
||||
else:
|
||||
if status is not None:
|
||||
if status:
|
||||
print('FAILED')
|
||||
failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
|
||||
else:
|
||||
@@ -77,13 +94,13 @@ def runAllTests( jsontest_executable_path, input_dir = None,
|
||||
base_path = os.path.splitext(input_path)[0]
|
||||
actual_output = safeReadFile( base_path + '.actual' )
|
||||
actual_rewrite_output = safeReadFile( base_path + '.actual-rewrite' )
|
||||
file(base_path + '.process-output','wt').write( process_output )
|
||||
open(base_path + '.process-output', 'wt', encoding = 'utf-8').write( process_output )
|
||||
if status:
|
||||
print('parsing failed')
|
||||
failed_tests.append( (input_path, 'Parsing failed:\n' + process_output) )
|
||||
else:
|
||||
expected_output_path = os.path.splitext(input_path)[0] + '.expected'
|
||||
expected_output = file( expected_output_path, 'rt' ).read()
|
||||
expected_output = open( expected_output_path, 'rt', encoding = 'utf-8' ).read()
|
||||
detail = ( compareOutputs( expected_output, actual_output, 'input' )
|
||||
or compareOutputs( expected_output, actual_rewrite_output, 'rewrite' ) )
|
||||
if detail:
|
||||
|
@@ -1,4 +1,6 @@
|
||||
from __future__ import print_function
|
||||
from __future__ import unicode_literals
|
||||
from io import open
|
||||
from glob import glob
|
||||
import sys
|
||||
import os
|
||||
@@ -19,7 +21,11 @@ class TestProxy(object):
|
||||
else:
|
||||
cmd = []
|
||||
cmd.extend( [self.test_exe_path, '--test-auto'] + options )
|
||||
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
try:
|
||||
process = subprocess.Popen( cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
|
||||
except:
|
||||
print(cmd)
|
||||
raise
|
||||
stdout = process.communicate()[0]
|
||||
if process.returncode:
|
||||
return False, stdout
|
||||
@@ -31,7 +37,7 @@ def runAllTests( exe_path, use_valgrind=False ):
|
||||
if not status:
|
||||
print("Failed to obtain unit tests list:\n" + test_names, file=sys.stderr)
|
||||
return 1
|
||||
test_names = [name.strip() for name in test_names.strip().split('\n')]
|
||||
test_names = [name.strip() for name in test_names.decode('utf-8').strip().split('\n')]
|
||||
failures = []
|
||||
for name in test_names:
|
||||
print('TESTING %s:' % name, end=' ')
|
||||
|
Reference in New Issue
Block a user