diff --git a/.travis.yml b/.travis.yml index 6d7ccde..23acd4e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,5 @@ # Build matrix / environment variables are explained on: -# http://about.travis-ci.org/docs/user/build-configuration/ +# http://about.travis-ci.com/docs/user/build-configuration/ # This file can be validated on: http://www.yamllint.com/ # Or using the Ruby based travel command line tool: # gem install travis --no-rdoc --no-ri diff --git a/.travis_scripts/meson_builder.sh b/.travis_scripts/meson_builder.sh index 1fdd8f6..bc74732 100755 --- a/.travis_scripts/meson_builder.sh +++ b/.travis_scripts/meson_builder.sh @@ -64,7 +64,7 @@ ninja --version _COMPILER_NAME=`basename ${CXX}` _BUILD_DIR_NAME="build-${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}" -./.travis_scripts/run-clang-format.sh +#./.travis_scripts/run-clang-format.sh meson --fatal-meson-warnings --werror --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . "${_BUILD_DIR_NAME}" ninja -v -j 2 -C "${_BUILD_DIR_NAME}" diff --git a/BUILD.bazel b/BUILD.bazel new file mode 100644 index 0000000..6d7ac3d --- /dev/null +++ b/BUILD.bazel @@ -0,0 +1,37 @@ +licenses(["unencumbered"]) # Public Domain or MIT + +exports_files(["LICENSE"]) + +cc_library( + name = "jsoncpp", + srcs = [ + "src/lib_json/json_reader.cpp", + "src/lib_json/json_tool.h", + "src/lib_json/json_value.cpp", + "src/lib_json/json_writer.cpp", + ], + hdrs = [ + "include/json/allocator.h", + "include/json/assertions.h", + "include/json/config.h", + "include/json/json_features.h", + "include/json/forwards.h", + "include/json/json.h", + "include/json/reader.h", + "include/json/value.h", + "include/json/version.h", + "include/json/writer.h", + ], + copts = [ + "-DJSON_USE_EXCEPTION=0", + "-DJSON_HAS_INT64", + ], + includes = ["include"], + visibility = ["//visibility:public"], + deps = [":private"], +) + +cc_library( + name = "private", + textual_hdrs = ["src/lib_json/json_valueiterator.inl"], +) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ad82f9..fd8bcf2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ # policies that provide successful builds. By setting JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION # to a value greater than the oldest policies, all policies between # JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION (used for this build) -# are set to their NEW behaivor, thereby suppressing policy warnings related to policies +# are set to their NEW behavior, thereby suppressing policy warnings related to policies # between the JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION. # # CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will @@ -72,11 +72,11 @@ project(jsoncpp # 2. ./include/json/version.h # 3. ./CMakeLists.txt # IMPORTANT: also update the PROJECT_SOVERSION!! - VERSION 1.9.4 # [.[.[.]]] + VERSION 1.9.5 # [.[.[.]]] LANGUAGES CXX) message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") -set(PROJECT_SOVERSION 24) +set(PROJECT_SOVERSION 25) include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake) include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake) @@ -134,7 +134,11 @@ endif() if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") # using regular Clang or AppleClang - add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare) + add_compile_options(-Wall -Wconversion -Wshadow) + + if(JSONCPP_WITH_WARNING_AS_ERROR) + add_compile_options(-Werror=conversion -Werror=sign-compare) + endif() elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # using GCC add_compile_options(-Wall -Wconversion -Wshadow -Wextra) @@ -148,9 +152,11 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") endif() elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") # using Intel compiler - add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion) + add_compile_options(-Wall -Wconversion -Wshadow -Wextra) - if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR) + if(JSONCPP_WITH_WARNING_AS_ERROR) + add_compile_options(-Werror=conversion) + elseif(JSONCPP_WITH_STRICT_ISO) add_compile_options(-Wpedantic) endif() endif() @@ -177,11 +183,16 @@ if(JSONCPP_WITH_CMAKE_PACKAGE) include(CMakePackageConfigHelpers) install(EXPORT jsoncpp DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp - FILE jsoncppConfig.cmake) + FILE jsoncpp-targets.cmake) + configure_package_config_file(jsoncppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake + INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp) + write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake" VERSION ${PROJECT_VERSION} COMPATIBILITY SameMajorVersion) - install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake + install(FILES + ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake + ${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp-namespaced-targets.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp) endif() diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d992be..5f5c032 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -77,7 +77,7 @@ See `doxybuild.py --help` for options. To add a test, you need to create two files in test/data: * a `TESTNAME.json` file, that contains the input document in JSON format. -* a `TESTNAME.expected` file, that contains a flatened representation of the +* a `TESTNAME.expected` file, that contains a flattened representation of the input document. The `TESTNAME.expected` file format is as follows: diff --git a/example/readFromString/readFromString.cpp b/example/readFromString/readFromString.cpp index c27bbd5..0b29a4e 100644 --- a/example/readFromString/readFromString.cpp +++ b/example/readFromString/readFromString.cpp @@ -1,5 +1,6 @@ #include "json/json.h" #include +#include /** * \brief Parse a raw string into Value object using the CharReaderBuilder * class, or the legacy Reader class. diff --git a/example/streamWrite/streamWrite.cpp b/example/streamWrite/streamWrite.cpp index 6f7f797..a72f5a5 100644 --- a/example/streamWrite/streamWrite.cpp +++ b/example/streamWrite/streamWrite.cpp @@ -1,5 +1,6 @@ #include "json/json.h" #include +#include /** \brief Write the Value object to a stream. * Example Usage: * $g++ streamWrite.cpp -ljsoncpp -std=c++11 -o streamWrite diff --git a/include/json/reader.h b/include/json/reader.h index 847cd37..4fabe6b 100644 --- a/include/json/reader.h +++ b/include/json/reader.h @@ -33,8 +33,7 @@ namespace Json { * \deprecated Use CharReader and CharReaderBuilder. */ -class JSONCPP_DEPRECATED( - "Use CharReader and CharReaderBuilder instead.") JSON_API Reader { +class JSON_API Reader { public: using Char = char; using Location = const Char*; @@ -51,13 +50,13 @@ public: }; /** \brief Constructs a Reader allowing all features for parsing. + * \deprecated Use CharReader and CharReaderBuilder. */ - JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(); /** \brief Constructs a Reader allowing the specified feature set for parsing. + * \deprecated Use CharReader and CharReaderBuilder. */ - JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead") Reader(const Features& features); /** \brief Read a Value from a JSON @@ -337,6 +336,9 @@ public: * - `"allowSpecialFloats": false or true` * - If true, special float values (NaNs and infinities) are allowed and * their values are lossfree restorable. + * - `"skipBom": false or true` + * - If true, if the input starts with the Unicode byte order mark (BOM), + * it is skipped. * * You can examine 'settings_` yourself to see the defaults. You can also * write and read them just like any JSON Value. diff --git a/include/json/version.h b/include/json/version.h index 87cf7e2..e931d03 100644 --- a/include/json/version.h +++ b/include/json/version.h @@ -9,10 +9,10 @@ // 3. /CMakeLists.txt // IMPORTANT: also update the SOVERSION!! -#define JSONCPP_VERSION_STRING "1.9.4" +#define JSONCPP_VERSION_STRING "1.9.5" #define JSONCPP_VERSION_MAJOR 1 #define JSONCPP_VERSION_MINOR 9 -#define JSONCPP_VERSION_PATCH 4 +#define JSONCPP_VERSION_PATCH 5 #define JSONCPP_VERSION_QUALIFIER #define JSONCPP_VERSION_HEXA \ ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \ diff --git a/include/json/writer.h b/include/json/writer.h index 99d74c7..03f9906 100644 --- a/include/json/writer.h +++ b/include/json/writer.h @@ -147,7 +147,7 @@ public: /** \brief Abstract class for writers. * \deprecated Use StreamWriter. (And really, this is an implementation detail.) */ -class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer { +class JSON_API Writer { public: virtual ~Writer(); @@ -167,7 +167,7 @@ public: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter +class JSON_API FastWriter : public Writer { public: FastWriter(); @@ -217,7 +217,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their *#CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -227,7 +227,7 @@ private: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API +class JSON_API StyledWriter : public Writer { public: StyledWriter(); @@ -286,7 +286,7 @@ private: * - otherwise, it the values do not fit on one line, or the array contains * object or non empty array, then print one value per line. * - * If the Value have comments then they are outputed according to their + * If the Value have comments then they are outputted according to their #CommentPlacement. * * \sa Reader, Value, Value::setComment() @@ -296,7 +296,7 @@ private: #pragma warning(push) #pragma warning(disable : 4996) // Deriving from deprecated class #endif -class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API +class JSON_API StyledStreamWriter { public: /** diff --git a/jsoncpp-namespaced-targets.cmake b/jsoncpp-namespaced-targets.cmake new file mode 100644 index 0000000..ac1504e --- /dev/null +++ b/jsoncpp-namespaced-targets.cmake @@ -0,0 +1,7 @@ +if (TARGET jsoncpp_static) + add_library(JsonCpp::JsonCpp INTERFACE IMPORTED) + set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_static") +elseif (TARGET jsoncpp_lib) + add_library(JsonCpp::JsonCpp INTERFACE IMPORTED) + set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_lib") +endif () \ No newline at end of file diff --git a/jsoncppConfig.cmake.in b/jsoncppConfig.cmake.in new file mode 100644 index 0000000..76570bc --- /dev/null +++ b/jsoncppConfig.cmake.in @@ -0,0 +1,11 @@ +cmake_policy(PUSH) +cmake_policy(VERSION 3.0) + +@PACKAGE_INIT@ + +include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-targets.cmake" ) +include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" ) + +check_required_components(JsonCpp) + +cmake_policy(POP) diff --git a/meson.build b/meson.build index 08e0f29..f68db30 100644 --- a/meson.build +++ b/meson.build @@ -50,7 +50,7 @@ jsoncpp_lib = library( 'src/lib_json/json_value.cpp', 'src/lib_json/json_writer.cpp', ]), - soversion : 24, + soversion : 25, install : true, include_directories : jsoncpp_include_directories, cpp_args: dll_export_flag) diff --git a/src/lib_json/CMakeLists.txt b/src/lib_json/CMakeLists.txt index ae406c0..3cf66eb 100644 --- a/src/lib_json/CMakeLists.txt +++ b/src/lib_json/CMakeLists.txt @@ -11,20 +11,10 @@ include(CheckCXXSymbolExists) check_include_file_cxx(clocale HAVE_CLOCALE) check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV) -if(CMAKE_VERSION VERSION_LESS 3.0.0) - # The "LANGUAGE CXX" parameter is not supported in CMake versions below 3, - # so the C compiler and header has to be used. - check_include_file(locale.h HAVE_LOCALE_H) - set(CMAKE_EXTRA_INCLUDE_FILES locale.h) - check_type_size("struct lconv" LCONV_SIZE) - unset(CMAKE_EXTRA_INCLUDE_FILES) - check_struct_has_member("struct lconv" decimal_point locale.h HAVE_DECIMAL_POINT) -else() - set(CMAKE_EXTRA_INCLUDE_FILES clocale) - check_type_size(lconv LCONV_SIZE LANGUAGE CXX) - unset(CMAKE_EXTRA_INCLUDE_FILES) - check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX) -endif() +set(CMAKE_EXTRA_INCLUDE_FILES clocale) +check_type_size(lconv LCONV_SIZE LANGUAGE CXX) +unset(CMAKE_EXTRA_INCLUDE_FILES) +check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX) if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV)) message(WARNING "Locale functionality is not supported") @@ -129,7 +119,7 @@ if(BUILD_SHARED_LIBS) OUTPUT_NAME jsoncpp VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_SOVERSION} - POSITION_INDEPENDENT_CODE ON + POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) # Set library's runtime search path on OSX @@ -139,13 +129,11 @@ if(BUILD_SHARED_LIBS) target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES}) - if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) - target_include_directories(${SHARED_LIB} PUBLIC - $ - $ - $ - ) - endif() + target_include_directories(${SHARED_LIB} PUBLIC + $ + $ + $ + ) list(APPEND CMAKE_TARGETS ${SHARED_LIB}) endif() @@ -154,7 +142,7 @@ if(BUILD_STATIC_LIBS) set(STATIC_LIB ${PROJECT_NAME}_static) add_library(${STATIC_LIB} STATIC ${PUBLIC_HEADERS} ${JSONCPP_SOURCES}) - # avoid name clashes on windows as the shared import lib is alse named jsoncpp.lib + # avoid name clashes on windows as the shared import lib is also named jsoncpp.lib if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS) if (MSVC) set(STATIC_SUFFIX "_static") @@ -175,13 +163,11 @@ if(BUILD_STATIC_LIBS) target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES}) - if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) - target_include_directories(${STATIC_LIB} PUBLIC - $ - $ - $ - ) - endif() + target_include_directories(${STATIC_LIB} PUBLIC + $ + $ + $ + ) list(APPEND CMAKE_TARGETS ${STATIC_LIB}) endif() @@ -194,7 +180,7 @@ if(BUILD_OBJECT_LIBS) OUTPUT_NAME jsoncpp VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_SOVERSION} - POSITION_INDEPENDENT_CODE ON + POSITION_INDEPENDENT_CODE ${BUILD_SHARED_LIBS} ) # Set library's runtime search path on OSX @@ -204,13 +190,11 @@ if(BUILD_OBJECT_LIBS) target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES}) - if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) - target_include_directories(${OBJECT_LIB} PUBLIC - $ - $ - $ - ) - endif() + target_include_directories(${OBJECT_LIB} PUBLIC + $ + $ + $ + ) list(APPEND CMAKE_TARGETS ${OBJECT_LIB}) endif() diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp index 63fc116..719a35a 100644 --- a/src/lib_json/json_reader.cpp +++ b/src/lib_json/json_reader.cpp @@ -12,6 +12,7 @@ #endif // if !defined(JSON_IS_AMALGAMATION) #include #include +#include #include #include #include @@ -104,8 +105,7 @@ bool Reader::parse(std::istream& is, Value& root, bool collectComments) { // Since String is reference-counted, this at least does not // create an extra copy. - String doc; - std::getline(is, doc, static_cast EOF); + String doc(std::istreambuf_iterator(is), {}); return parse(doc.data(), doc.data() + doc.size(), root, collectComments); } @@ -601,9 +601,15 @@ bool Reader::decodeDouble(Token& token, Value& decoded) { double value = 0; String buffer(token.start_, token.end_); IStringStream is(buffer); - if (!(is >> value)) - return addError( + if (!(is >> value)) { + if (value == std::numeric_limits::max()) + value = std::numeric_limits::infinity(); + else if (value == std::numeric_limits::lowest()) + value = -std::numeric_limits::infinity(); + else if (!std::isinf(value)) + return addError( "'" + String(token.start_, token.end_) + "' is not a number.", token); + } decoded = value; return true; } @@ -1603,7 +1609,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) { const auto digit(static_cast(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, meaing value == threshold, + // a) we've only just touched the limit, meaning value == threshold, // b) this is the last digit, or // c) it's small enough to fit in that rounding delta, we're okay. // Otherwise treat this number as a double to avoid overflow. @@ -1643,7 +1649,12 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) { const String buffer(token.start_, token.end_); IStringStream is(buffer); if (!(is >> value)) { - return addError( + if (value == std::numeric_limits::max()) + value = std::numeric_limits::infinity(); + else if (value == std::numeric_limits::lowest()) + value = -std::numeric_limits::infinity(); + else if (!std::isinf(value)) + return addError( "'" + String(token.start_, token.end_) + "' is not a number.", token); } decoded = value; diff --git a/src/test_lib_json/jsontest.h b/src/test_lib_json/jsontest.h index 4e8af0f..a2385fa 100644 --- a/src/test_lib_json/jsontest.h +++ b/src/test_lib_json/jsontest.h @@ -74,7 +74,7 @@ public: /// Removes the last PredicateContext added to the predicate stack /// chained list. - /// Next messages will be targed at the PredicateContext that was removed. + /// Next messages will be targeted at the PredicateContext that was removed. TestResult& popPredicateContext(); bool failed() const; diff --git a/test/data/legacy_test_real_13.expected b/test/data/legacy_test_real_13.expected new file mode 100644 index 0000000..8d3f03f --- /dev/null +++ b/test/data/legacy_test_real_13.expected @@ -0,0 +1,3 @@ +.=[] +.[0]=-inf +.[1]=inf diff --git a/test/data/legacy_test_real_13.json b/test/data/legacy_test_real_13.json new file mode 100644 index 0000000..287258a --- /dev/null +++ b/test/data/legacy_test_real_13.json @@ -0,0 +1 @@ +[-1e+9999, 1e+9999]