Merge branch 'master' into prevent-in-source-builds

This commit is contained in:
Jordan Bayles 2020-11-06 11:53:58 -08:00
commit f321cd0388
51 changed files with 1507 additions and 1107 deletions

View File

@ -1,5 +1,5 @@
---
Checks: 'google-readability-casting,modernize-use-default-member-init,modernize-use-using,readability-redundant-member-init'
Checks: 'google-readability-casting,modernize-deprecated-headers,modernize-loop-convert,modernize-use-auto,modernize-use-default-member-init,modernize-use-using,readability-else-after-return,readability-redundant-member-init,readability-redundant-string-cstr'
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false

1
.gitignore vendored
View File

@ -28,7 +28,6 @@
# CMake-generated files:
CMakeFiles/
*.cmake
/pkg-config/jsoncpp.pc
jsoncpp_lib_static.dir/

View File

@ -22,8 +22,6 @@ addons:
- clang-8
- valgrind
matrix:
allow_failures:
- os: osx
include:
- name: Mac clang meson static release testing
os: osx
@ -44,6 +42,8 @@ matrix:
CC="clang"
LIB_TYPE=static
BUILD_TYPE=release
PYTHONUSERBASE="$(pwd)/LOCAL"
PATH="$PYTHONUSERBASE/bin:$PATH"
# before_install and install steps only needed for linux meson builds
before_install:
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh

View File

@ -66,7 +66,7 @@ cmake --version
echo ${CXX}
${CXX} --version
_COMPILER_NAME=`basename ${CXX}`
if [ "${BUILD_TYPE}" == "shared" ]; then
if [ "${LIB_TYPE}" = "shared" ]; then
_CMAKE_BUILD_SHARED_LIBS=ON
else
_CMAKE_BUILD_SHARED_LIBS=OFF

View File

@ -353,4 +353,4 @@ def main():
if __name__ == '__main__':
sys.exit(main())
sys.exit(main())

View File

@ -1 +0,0 @@
# NOTHING TO DO HERE

View File

@ -1,10 +1,5 @@
set -vex
wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip
unzip -q ninja-linux.zip -d build
pip3 install meson
echo ${PATH}
ls /usr/local
ls /usr/local/bin
export PATH="${PWD}"/build:/usr/local/bin:/usr/bin:${PATH}
pip3 install --user meson ninja
which meson
which ninja

View File

@ -21,6 +21,7 @@ Braden McDorman <bmcdorman@gmail.com>
Brandon Myers <bmyers1788@gmail.com>
Brendan Drew <brendan.drew@daqri.com>
chason <cxchao802@gmail.com>
chenguoping <chenguopingdota@163.com>
Chris Gilling <cgilling@iparadigms.com>
Christopher Dawes <christopher.dawes.1981@googlemail.com>
Christopher Dunn <cdunn2001@gmail.com>
@ -97,6 +98,7 @@ selaselah <selah@outlook.com>
Sergiy80 <sil2004@gmail.com>
sergzub <sergzub@gmail.com>
Stefan Schweter <stefan@schweter.it>
Stefano Fiorentino <stefano.fiore84@gmail.com>
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
Steven Hahn <hahnse@ornl.gov>
Stuart Eichert <stuart@fivemicro.com>

View File

@ -37,44 +37,43 @@ foreach(pold "") # Currently Empty
endif()
endforeach()
# ==== Define language standard configurations requiring at least c++11 standard
if(CMAKE_CXX_STANDARD EQUAL "98" )
message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported.")
endif()
# Build the library with C++11 standard support, independent from other including
# software which may use a different CXX_STANDARD or CMAKE_CXX_STANDARD.
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
#####
## Set the default target properties
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11) # Supported values are ``11``, ``14``, and ``17``.
endif()
if(NOT CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
# ====
# Ensures that CMAKE_BUILD_TYPE has a default value
if(NOT DEFINED CMAKE_BUILD_TYPE)
# Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
endif()
project(JSONCPP
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# ---------------------------------------------------------------------------
# use ccache if found, has to be done before project()
# ---------------------------------------------------------------------------
find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin)
if(CCACHE_EXECUTABLE)
message(STATUS "use ccache")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
endif()
project(jsoncpp
# Note: version must be updated in three places when doing a release. This
# annoying process ensures that amalgamate, CMake, and meson all report the
# correct version.
# 1. /meson.build
# 2. /include/json/version.h
# 3. /CMakeLists.txt
# IMPORTANT: also update the SOVERSION!!
VERSION 1.9.2 # <major>[.<minor>[.<patch>[.<tweak>]]]
# 1. ./meson.build
# 2. ./include/json/version.h
# 3. ./CMakeLists.txt
# IMPORTANT: also update the PROJECT_SOVERSION!!
VERSION 1.9.4 # <major>[.<minor>[.<patch>[.<tweak>]]]
LANGUAGES CXX)
message(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
set( JSONCPP_SOVERSION 22 )
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(PROJECT_SOVERSION 24)
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake)
@ -85,120 +84,80 @@ option(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occ
option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON)
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF)
# Enable runtime search path support for dynamic libraries on OSX
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
endif()
option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
option(BUILD_OBJECT_LIBS "Build jsoncpp_lib as a object library." ON)
# Adhere to GNU filesystem layout conventions
include(GNUInstallDirs)
set(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Archive output dir.")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Library output dir.")
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "PDB (MSVC debug symbol)output dir.")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL" )
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL")
configure_file( "${PROJECT_SOURCE_DIR}/version.in"
"${PROJECT_BINARY_DIR}/version"
NEWLINE_STYLE UNIX )
configure_file("${PROJECT_SOURCE_DIR}/version.in"
"${PROJECT_BINARY_DIR}/version"
NEWLINE_STYLE UNIX)
macro(UseCompilationWarningAsError)
macro(use_compilation_warning_as_error)
if(MSVC)
# Only enabled in debug because some old versions of VS STL generate
# warnings when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/WX>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
endif()
add_compile_options($<$<CONFIG:Debug>:/WX>)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
add_compile_options(-Werror)
if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic-errors)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
endif()
endif()
endif()
endmacro()
# Include our configuration header
include_directories( ${jsoncpp_SOURCE_DIR}/include )
include_directories(${jsoncpp_SOURCE_DIR}/include)
if(MSVC)
# Only enabled in debug because some old versions of VS STL generate
# unreachable code warning when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/W4>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
endif()
add_compile_options($<$<CONFIG:Debug>:/W4>)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# using GCC
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
# not yet ready for -Wsign-conversion
if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
add_compile_options(-Wpedantic)
endif()
if(JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
endif()
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
# using Intel compiler
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
add_compile_options(-Wpedantic)
endif()
endif()
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)
if(JSONCPP_WITH_WARNING_AS_ERROR)
UseCompilationWarningAsError()
use_compilation_warning_as_error()
endif()
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
include(JoinPaths)
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file(
"pkg-config/jsoncpp.pc.in"
"pkg-config/jsoncpp.pc"
@ -208,27 +167,29 @@ if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
endif()
if(JSONCPP_WITH_CMAKE_PACKAGE)
include (CMakePackageConfigHelpers)
install(EXPORT jsoncpp
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
FILE jsoncppConfig.cmake)
write_basic_package_version_file ("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
include(CMakePackageConfigHelpers)
install(EXPORT jsoncpp
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
FILE jsoncppConfig.cmake)
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
endif()
if(JSONCPP_WITH_TESTS)
enable_testing()
include(CTest)
enable_testing()
include(CTest)
endif()
# Build the different applications
add_subdirectory( src )
add_subdirectory(src)
#install the includes
add_subdirectory( include )
add_subdirectory(include)
#install the example
add_subdirectory( example )
if(JSONCPP_WITH_EXAMPLE)
add_subdirectory(example)
endif()

View File

@ -27,8 +27,13 @@ Then,
#LIB_TYPE=static
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
ninja -v -C build-${LIB_TYPE}
cd build-${LIB_TYPE}
meson test --no-rebuild --print-errorlogs
ninja -C build-static/ test
# Or
#cd build-${LIB_TYPE}
#meson test --no-rebuild --print-errorlogs
sudo ninja install
```

View File

@ -30,8 +30,14 @@ format to store user input files.
* `1.y.z` is built with C++11.
* `0.y.z` can be used with older compilers.
* `00.11.z` can be used both in old and new compilers.
* Major versions maintain binary-compatibility.
### Special note
The branch `00.11.z`is a new branch, its major version number `00` is to show that it is
different from `0.y.z` and `1.y.z`, the main purpose of this branch is to make a balance
between the other two branches. Thus, users can use some new features in this new branch
that introduced in 1.y.z, but can hardly applied into 0.y.z.
## Using JsonCpp in your project
@ -42,7 +48,7 @@ You can download and install JsonCpp using the [vcpkg](https://github.com/Micros
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
vcpkg install jsoncpp
./vcpkg install jsoncpp
The JsonCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.

View File

@ -99,6 +99,8 @@ def amalgamate_source(source_top_dir=None,
header.add_text("/// If defined, indicates that the source file is amalgamated")
header.add_text("/// to prevent private header inclusion.")
header.add_text("#define JSON_IS_AMALGAMATION")
header.add_file(os.path.join(INCLUDE_PATH, "version.h"))
header.add_file(os.path.join(INCLUDE_PATH, "allocator.h"))
header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")

23
cmake/JoinPaths.cmake Normal file
View File

@ -0,0 +1,23 @@
# This module provides a function for joining paths
# known from most languages
#
# SPDX-License-Identifier: (MIT OR CC0-1.0)
# Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips
#
# Modelled after Pythons os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()

View File

@ -1,29 +1,27 @@
#vim: et ts =4 sts = 4 sw = 4 tw = 0
cmake_minimum_required(VERSION 3.1)
set(EXAMPLES
readFromString
readFromStream
stringWrite
streamWrite
)
readFromString
readFromStream
stringWrite
streamWrite
)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra ")
else()
add_definitions(
-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-D_WIN32_WINNT=0x601
-D_WINSOCK_DEPRECATED_NO_WARNINGS)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
add_compile_options(-Wall -Wextra)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
add_definitions(
-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-D_WIN32_WINNT=0x601
-D_WINSOCK_DEPRECATED_NO_WARNINGS
)
endif()
foreach (example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(${example} jsoncpp_lib)
foreach(example ${EXAMPLES})
add_executable(${example} ${example}/${example}.cpp)
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
target_link_libraries(${example} jsoncpp_lib)
endforeach()
add_custom_target(examples ALL DEPENDS ${EXAMPLES})

View File

@ -11,7 +11,7 @@
*/
int main() {
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
const int rawJsonLength = static_cast<int>(rawJson.length());
const auto rawJsonLength = static_cast<int>(rawJson.length());
constexpr bool shouldUseOldWay = false;
JSONCPP_STRING err;
Json::Value root;

View File

@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
@ -35,11 +35,10 @@ public:
* Release memory which was allocated for N items at pointer P.
*
* The memory block is filled with zeroes before being released.
* The pointer argument is tagged as "volatile" to prevent the
* compiler optimizing out this critical step.
*/
void deallocate(volatile pointer p, size_type n) {
std::memset(p, 0, n * sizeof(T));
void deallocate(pointer p, size_type n) {
// memset_s is used because memset may be optimized away by the compiler
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
// free using "global operator delete"
::operator delete(p);
}
@ -86,4 +85,4 @@ bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
#pragma pack(pop)
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
#endif // JSON_ALLOCATOR_H_INCLUDED

View File

@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
#ifndef JSON_ASSERTIONS_H_INCLUDED
#define JSON_ASSERTIONS_H_INCLUDED
#include <cstdlib>
#include <sstream>
@ -21,19 +21,19 @@
// @todo <= add detail about condition in exception
#define JSON_ASSERT(condition) \
{ \
do { \
if (!(condition)) { \
Json::throwLogicError("assert json failed"); \
} \
}
} while (0)
#define JSON_FAIL_MESSAGE(message) \
{ \
do { \
OStringStream oss; \
oss << message; \
Json::throwLogicError(oss.str()); \
abort(); \
}
} while (0)
#else // JSON_USE_EXCEPTION
@ -52,8 +52,10 @@
#endif
#define JSON_ASSERT_MESSAGE(condition, message) \
if (!(condition)) { \
JSON_FAIL_MESSAGE(message); \
}
do { \
if (!(condition)) { \
JSON_FAIL_MESSAGE(message); \
} \
} while (0)
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
#endif // JSON_ASSERTIONS_H_INCLUDED

View File

@ -1,25 +0,0 @@
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
// Distributed under MIT license, or public domain if desired and
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef JSON_AUTOLINK_H_INCLUDED
#define JSON_AUTOLINK_H_INCLUDED
#include "config.h"
#ifdef JSON_IN_CPPTL
#include <cpptl/cpptl_autolink.h>
#endif
#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \
!defined(JSON_IN_CPPTL)
#define CPPTL_AUTOLINK_NAME "json"
#undef CPPTL_AUTOLINK_DLL
#ifdef JSON_DLL
#define CPPTL_AUTOLINK_DLL
#endif
#include "autolink.h"
#endif
#endif // JSON_AUTOLINK_H_INCLUDED

View File

@ -14,16 +14,6 @@
#include <string>
#include <type_traits>
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION
@ -40,28 +30,22 @@
/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL
#include <cpptl/config.h>
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
// Export macros for DLL visibility
#if defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL
#endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API)
#define JSON_API
#endif
@ -90,20 +74,6 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
// C++11 should be used directly in JSONCPP.
#define JSONCPP_OVERRIDE override
#if __cplusplus >= 201103L
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER < 1900
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT
#endif
#ifdef __clang__
#if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
@ -135,23 +105,23 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
using Int = int;
using UInt = unsigned int;
#if defined(JSON_NO_INT64)
typedef int LargestInt;
typedef unsigned int LargestUInt;
using LargestInt = int;
using LargestUInt = unsigned int;
#undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64;
typedef unsigned __int64 UInt64;
using Int64 = __int64;
using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64;
typedef uint64_t UInt64;
using Int64 = int64_t;
using UInt64 = uint64_t;
#endif // if defined(_MSC_VER)
typedef Int64 LargestInt;
typedef UInt64 LargestUInt;
using LargestInt = Int64;
using LargestUInt = UInt64;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)

View File

@ -29,7 +29,7 @@ class CharReaderBuilder;
class Features;
// value.h
typedef unsigned int ArrayIndex;
using ArrayIndex = unsigned int;
class StaticString;
class Path;
class PathArgument;

View File

@ -6,7 +6,7 @@
#ifndef JSON_JSON_H_INCLUDED
#define JSON_JSON_H_INCLUDED
#include "autolink.h"
#include "config.h"
#include "json_features.h"
#include "reader.h"
#include "value.h"

View File

@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
#define CPPTL_JSON_FEATURES_H_INCLUDED
#ifndef JSON_FEATURES_H_INCLUDED
#define JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
@ -58,4 +58,4 @@ public:
#pragma pack(pop)
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
#endif // JSON_FEATURES_H_INCLUDED

View File

@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_READER_H_INCLUDED
#define CPPTL_JSON_READER_H_INCLUDED
#ifndef JSON_READER_H_INCLUDED
#define JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "json_features.h"
@ -36,8 +36,8 @@ namespace Json {
class JSONCPP_DEPRECATED(
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
public:
typedef char Char;
typedef const Char* Location;
using Char = char;
using Location = const Char*;
/** \brief An error tagged with where in the JSON text it was encountered.
*
@ -187,7 +187,7 @@ private:
Location extra_;
};
typedef std::deque<ErrorInfo> Errors;
using Errors = std::deque<ErrorInfo>;
bool readToken(Token& token);
void skipSpaces();
@ -226,7 +226,7 @@ private:
static bool containsNewLine(Location begin, Location end);
static String normalizeEOL(Location begin, Location end);
typedef std::stack<Value*> Nodes;
using Nodes = std::stack<Value*>;
Nodes nodes_;
Errors errors_;
String document_;
@ -299,6 +299,8 @@ public:
* if allowComments is false.
* - `"allowComments": false or true`
* - true if comments are allowed.
* - `"allowTrailingCommas": false or true`
* - true if trailing commas in objects and arrays are allowed.
* - `"strictRoot": false or true`
* - true if root must be either an array or an object value
* - `"allowDroppedNullPlaceholders": false or true`
@ -398,4 +400,4 @@ JSON_API IStream& operator>>(IStream&, Value&);
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_READER_H_INCLUDED
#endif // JSON_READER_H_INCLUDED

View File

@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_H_INCLUDED
#define CPPTL_JSON_H_INCLUDED
#ifndef JSON_H_INCLUDED
#define JSON_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
@ -21,21 +21,31 @@
#endif
#endif
// Support for '= delete' with template declarations was a late addition
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
// even though these declare themselves to be c++11 compilers.
#if !defined(JSONCPP_TEMPLATE_DELETE)
#if defined(__clang__) && defined(__apple_build_version__)
#if __apple_build_version__ <= 8000042
#define JSONCPP_TEMPLATE_DELETE
#endif
#elif defined(__clang__)
#if __clang_major__ == 3 && __clang_minor__ <= 8
#define JSONCPP_TEMPLATE_DELETE
#endif
#endif
#if !defined(JSONCPP_TEMPLATE_DELETE)
#define JSONCPP_TEMPLATE_DELETE = delete
#endif
#endif
#include <array>
#include <exception>
#include <map>
#include <memory>
#include <string>
#include <vector>
#ifndef JSON_USE_CPPTL_SMALLMAP
#include <map>
#else
#include <cpptl/smallmap.h>
#endif
#ifdef JSON_USE_CPPTL
#include <cpptl/forwards.h>
#endif
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@ -57,8 +67,8 @@ namespace Json {
class JSON_API Exception : public std::exception {
public:
Exception(String msg);
~Exception() JSONCPP_NOEXCEPT override;
char const* what() const JSONCPP_NOEXCEPT override;
~Exception() noexcept override;
char const* what() const noexcept override;
protected:
String msg_;
@ -120,11 +130,6 @@ enum PrecisionType {
decimalPlaces ///< we set max number of digits after "." in string
};
//# ifdef JSON_USE_CPPTL
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
//# endif
/** \brief Lightweight wrapper to tag static string.
*
* Value constructor and objectValue member assignment takes advantage of the
@ -189,21 +194,21 @@ class JSON_API Value {
friend class ValueIteratorBase;
public:
typedef std::vector<String> Members;
typedef ValueIterator iterator;
typedef ValueConstIterator const_iterator;
typedef Json::UInt UInt;
typedef Json::Int Int;
using Members = std::vector<String>;
using iterator = ValueIterator;
using const_iterator = ValueConstIterator;
using UInt = Json::UInt;
using Int = Json::Int;
#if defined(JSON_HAS_INT64)
typedef Json::UInt64 UInt64;
typedef Json::Int64 Int64;
using UInt64 = Json::UInt64;
using Int64 = Json::Int64;
#endif // defined(JSON_HAS_INT64)
typedef Json::LargestInt LargestInt;
typedef Json::LargestUInt LargestUInt;
typedef Json::ArrayIndex ArrayIndex;
using LargestInt = Json::LargestInt;
using LargestUInt = Json::LargestUInt;
using ArrayIndex = Json::ArrayIndex;
// Required for boost integration, e. g. BOOST_TEST
typedef std::string value_type;
using value_type = std::string;
#if JSON_USE_NULLREF
// Binary compatibility kludges, do not use.
@ -287,11 +292,7 @@ private:
};
public:
#ifndef JSON_USE_CPPTL_SMALLMAP
typedef std::map<CZString, Value> ObjectValues;
#else
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
#endif // ifndef JSON_USE_CPPTL_SMALLMAP
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public:
@ -340,10 +341,8 @@ public:
*/
Value(const StaticString& value);
Value(const String& value);
#ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString& value);
#endif
Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other);
Value(Value&& other);
~Value();
@ -384,9 +383,6 @@ public:
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
bool getString(char const** begin, char const** end) const;
#ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
#endif
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
@ -412,6 +408,10 @@ public:
bool isArray() const;
bool isObject() const;
/// The `as<T>` and `is<T>` member function templates and specializations.
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
bool isConvertibleTo(ValueType other) const;
/// Number of values in array or object
@ -422,7 +422,7 @@ public:
bool empty() const;
/// Return !isNull()
JSONCPP_OP_EXPLICIT operator bool() const;
explicit operator bool() const;
/// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue
@ -464,8 +464,10 @@ public:
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value);
Value& append(Value&& value);
/// \brief Insert value in array at specific index
bool insert(ArrayIndex index, Value newValue);
bool insert(ArrayIndex index, const Value& newValue);
bool insert(ArrayIndex index, Value&& newValue);
/// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
@ -494,13 +496,6 @@ public:
* \endcode
*/
Value& operator[](const StaticString& key);
#ifdef JSON_USE_CPPTL
/// Access an object value by name, create a null member if it does not exist.
Value& operator[](const CppTL::ConstString& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const CppTL::ConstString& key) const;
#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
@ -513,11 +508,6 @@ public:
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
#ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
#endif
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@ -563,10 +553,6 @@ public:
bool isMember(const String& key) const;
/// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const;
#ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
bool isMember(const CppTL::ConstString& key) const;
#endif
/// \brief Return a list of the member names.
///
@ -575,11 +561,6 @@ public:
/// \post if type() was nullValue, it remains nullValue
Members getMemberNames() const;
//# ifdef JSON_USE_CPPTL
// EnumMemberNames enumMemberNames() const;
// EnumValues enumValues() const;
//# endif
/// \deprecated Always pass len.
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
void setComment(const char* comment, CommentPlacement placement) {
@ -673,6 +654,36 @@ private:
ptrdiff_t limit_;
};
template <> inline bool Value::as<bool>() const { return asBool(); }
template <> inline bool Value::is<bool>() const { return isBool(); }
template <> inline Int Value::as<Int>() const { return asInt(); }
template <> inline bool Value::is<Int>() const { return isInt(); }
template <> inline UInt Value::as<UInt>() const { return asUInt(); }
template <> inline bool Value::is<UInt>() const { return isUInt(); }
#if defined(JSON_HAS_INT64)
template <> inline Int64 Value::as<Int64>() const { return asInt64(); }
template <> inline bool Value::is<Int64>() const { return isInt64(); }
template <> inline UInt64 Value::as<UInt64>() const { return asUInt64(); }
template <> inline bool Value::is<UInt64>() const { return isUInt64(); }
#endif
template <> inline double Value::as<double>() const { return asDouble(); }
template <> inline bool Value::is<double>() const { return isDouble(); }
template <> inline String Value::as<String>() const { return asString(); }
template <> inline bool Value::is<String>() const { return isString(); }
/// These `as` specializations are type conversions, and do not have a
/// corresponding `is`.
template <> inline float Value::as<float>() const { return asFloat(); }
template <> inline const char* Value::as<const char*>() const {
return asCString();
}
/** \brief Experimental and untested: represents an element of the "path" to
* access a node.
*/
@ -718,8 +729,8 @@ public:
Value& make(Value& root) const;
private:
typedef std::vector<const PathArgument*> InArgs;
typedef std::vector<PathArgument> Args;
using InArgs = std::vector<const PathArgument*>;
using Args = std::vector<PathArgument>;
void makePath(const String& path, const InArgs& in);
void addPathInArg(const String& path, const InArgs& in,
@ -734,10 +745,10 @@ private:
*/
class JSON_API ValueIteratorBase {
public:
typedef std::bidirectional_iterator_tag iterator_category;
typedef unsigned int size_t;
typedef int difference_type;
typedef ValueIteratorBase SelfType;
using iterator_category = std::bidirectional_iterator_tag;
using size_t = unsigned int;
using difference_type = int;
using SelfType = ValueIteratorBase;
bool operator==(const SelfType& other) const { return isEqual(other); }
@ -810,12 +821,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
friend class Value;
public:
typedef const Value value_type;
using value_type = const Value;
// typedef unsigned int size_t;
// typedef int difference_type;
typedef const Value& reference;
typedef const Value* pointer;
typedef ValueConstIterator SelfType;
using reference = const Value&;
using pointer = const Value*;
using SelfType = ValueConstIterator;
ValueConstIterator();
ValueConstIterator(ValueIterator const& other);
@ -861,12 +872,12 @@ class JSON_API ValueIterator : public ValueIteratorBase {
friend class Value;
public:
typedef Value value_type;
typedef unsigned int size_t;
typedef int difference_type;
typedef Value& reference;
typedef Value* pointer;
typedef ValueIterator SelfType;
using value_type = Value;
using size_t = unsigned int;
using difference_type = int;
using reference = Value&;
using pointer = Value*;
using SelfType = ValueIterator;
ValueIterator();
explicit ValueIterator(const ValueConstIterator& other);
@ -921,4 +932,4 @@ inline void swap(Value& a, Value& b) { a.swap(b); }
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_H_INCLUDED
#endif // JSON_H_INCLUDED

View File

@ -9,10 +9,10 @@
// 3. /CMakeLists.txt
// IMPORTANT: also update the SOVERSION!!
#define JSONCPP_VERSION_STRING "1.9.2"
#define JSONCPP_VERSION_STRING "1.9.4"
#define JSONCPP_VERSION_MAJOR 1
#define JSONCPP_VERSION_MINOR 9
#define JSONCPP_VERSION_PATCH 2
#define JSONCPP_VERSION_PATCH 4
#define JSONCPP_VERSION_QUALIFIER
#define JSONCPP_VERSION_HEXA \
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \

View File

@ -252,7 +252,7 @@ private:
static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text);
typedef std::vector<String> ChildValues;
using ChildValues = std::vector<String>;
ChildValues childValues_;
String document_;
@ -326,7 +326,7 @@ private:
static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text);
typedef std::vector<String> ChildValues;
using ChildValues = std::vector<String>;
ChildValues childValues_;
OStream* document_;

View File

@ -9,7 +9,7 @@ project(
# 2. /include/json/version.h
# 3. /CMakeLists.txt
# IMPORTANT: also update the SOVERSION!!
version : '1.9.2',
version : '1.9.4',
default_options : [
'buildtype=release',
'cpp_std=c++11',
@ -18,10 +18,9 @@ project(
meson_version : '>= 0.49.0')
jsoncpp_headers = [
jsoncpp_headers = files([
'include/json/allocator.h',
'include/json/assertions.h',
'include/json/autolink.h',
'include/json/config.h',
'include/json/json_features.h',
'include/json/forwards.h',
@ -29,7 +28,8 @@ jsoncpp_headers = [
'include/json/reader.h',
'include/json/value.h',
'include/json/version.h',
'include/json/writer.h']
'include/json/writer.h',
])
jsoncpp_include_directories = include_directories('include')
install_headers(
@ -45,13 +45,12 @@ else
endif
jsoncpp_lib = library(
'jsoncpp',
[ jsoncpp_headers,
'src/lib_json/json_tool.h',
'jsoncpp', files([
'src/lib_json/json_reader.cpp',
'src/lib_json/json_value.cpp',
'src/lib_json/json_writer.cpp'],
soversion : 22,
'src/lib_json/json_writer.cpp',
]),
soversion : 24,
install : true,
include_directories : jsoncpp_include_directories,
cpp_args: dll_export_flag)
@ -67,18 +66,21 @@ import('pkgconfig').generate(
jsoncpp_dep = declare_dependency(
include_directories : jsoncpp_include_directories,
link_with : jsoncpp_lib,
version : meson.project_version(),
)
version : meson.project_version())
# tests
if meson.is_subproject() or not get_option('tests')
subdir_done()
endif
python = import('python').find_installation()
jsoncpp_test = executable(
'jsoncpp_test',
[ 'src/test_lib_json/jsontest.cpp',
'src/test_lib_json/jsontest.h',
'jsoncpp_test', files([
'src/test_lib_json/jsontest.cpp',
'src/test_lib_json/main.cpp',
'src/test_lib_json/fuzz.cpp'],
'src/test_lib_json/fuzz.cpp',
]),
include_directories : jsoncpp_include_directories,
link_with : jsoncpp_lib,
install : false,
@ -101,5 +103,17 @@ test(
'-B',
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
jsontestrunner,
join_paths(meson.current_source_dir(), 'test/data')]
join_paths(meson.current_source_dir(), 'test/data')],
)
test(
'jsonchecker_jsontestrunner',
python,
is_parallel : false,
args : [
'-B',
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
'--with-json-checker',
jsontestrunner,
join_paths(meson.current_source_dir(), 'test/data')],
workdir : join_paths(meson.current_source_dir(), 'test/data'),
)

5
meson_options.txt Normal file
View File

@ -0,0 +1,5 @@
option(
'tests',
type : 'boolean',
value : true,
description : 'Enable building tests')

View File

@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
libdir=@libdir_for_pc_file@
includedir=@includedir_for_pc_file@
Name: jsoncpp
Description: A C++ library for interacting with JSON

1
reformat.sh Normal file
View File

@ -0,0 +1 @@
find src -name '*.cpp' -or -name '*.h' | xargs clang-format -i

View File

@ -1,26 +1,28 @@
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
# The new Python3 module is much more robust than the previous PythonInterp
find_package (Python3 COMPONENTS Interpreter)
# Set variables for backwards compatibility with cmake < 3.12.0
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
# The new Python3 module is much more robust than the previous PythonInterp
find_package(Python3 COMPONENTS Interpreter)
# Set variables for backwards compatibility with cmake < 3.12.0
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
else()
set(Python_ADDITIONAL_VERSIONS 3.8)
find_package(PythonInterp 3)
set(Python_ADDITIONAL_VERSIONS 3.8)
find_package(PythonInterp 3)
endif()
add_executable(jsontestrunner_exe
main.cpp
)
main.cpp
)
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions( -DJSON_DLL )
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions(-DJSON_DLL)
endif()
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
else()
target_link_libraries(jsontestrunner_exe jsoncpp_static)
endif()
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
@ -32,18 +34,18 @@ if(PYTHONINTERP_FOUND)
# Run unit tests in post-build
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
add_custom_target(jsoncpp_readerwriter_tests
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
DEPENDS jsontestrunner_exe jsoncpp_test
)
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
DEPENDS jsontestrunner_exe jsoncpp_test
)
add_custom_target(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
add_test(NAME jsoncpp_readerwriter
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
WORKING_DIRECTORY "${TEST_DIR}/data"
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
WORKING_DIRECTORY "${TEST_DIR}/data"
)
add_test(NAME jsoncpp_readerwriter_json_checker
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
WORKING_DIRECTORY "${TEST_DIR}/data"
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
WORKING_DIRECTORY "${TEST_DIR}/data"
)
endif()

View File

@ -57,10 +57,10 @@ static Json::String readInputTestFile(const char* path) {
if (!file)
return "";
fseek(file, 0, SEEK_END);
long const size = ftell(file);
size_t const usize = static_cast<unsigned long>(size);
auto const size = ftell(file);
auto const usize = static_cast<size_t>(size);
fseek(file, 0, SEEK_SET);
char* buffer = new char[size + 1];
auto buffer = new char[size + 1];
buffer[size] = 0;
Json::String text;
if (fread(buffer, 1, usize, file) == usize)
@ -111,7 +111,7 @@ static void printValueTree(FILE* fout, Json::Value& value,
Json::Value::Members members(value.getMemberNames());
std::sort(members.begin(), members.end());
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
for (auto name : members) {
for (const auto& name : members) {
printValueTree(fout, value[name], path + suffix + name);
}
} break;

View File

@ -1,13 +1,7 @@
if( CMAKE_COMPILER_IS_GNUCXX )
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
#-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 )
add_compile_options("-Werror=strict-aliasing")
endif()
include(CheckIncludeFileCXX)
include(CheckTypeSize)
@ -35,15 +29,15 @@ endif()
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
message(WARNING "Locale functionality is not supported")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
else()
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
endif()
endif()
set( JSONCPP_INCLUDE_DIR ../../include )
set(JSONCPP_INCLUDE_DIR ../../include)
set( PUBLIC_HEADERS
set(PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/config.h
${JSONCPP_INCLUDE_DIR}/json/forwards.h
${JSONCPP_INCLUDE_DIR}/json/json_features.h
@ -52,49 +46,29 @@ set( PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/version.h
${JSONCPP_INCLUDE_DIR}/json/writer.h
${JSONCPP_INCLUDE_DIR}/json/assertions.h
)
)
source_group( "Public API" FILES ${PUBLIC_HEADERS} )
source_group("Public API" FILES ${PUBLIC_HEADERS})
set(jsoncpp_sources
json_tool.h
json_reader.cpp
json_valueiterator.inl
json_value.cpp
json_writer.cpp)
set(JSONCPP_SOURCES
json_tool.h
json_reader.cpp
json_valueiterator.inl
json_value.cpp
json_writer.cpp
)
# Install instructions for this target
if(JSONCPP_WITH_CMAKE_PACKAGE)
set(INSTALL_EXPORT EXPORT jsoncpp)
else(JSONCPP_WITH_CMAKE_PACKAGE)
else()
set(INSTALL_EXPORT)
endif()
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL_BUILD )
else()
add_definitions( -DJSON_DLL_BUILD )
endif()
endif()
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
set_target_properties( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
set_target_properties( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
set_target_properties( jsoncpp_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
endif()
# Specify compiler features required when compiling a given target.
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
# for complete list of features available
target_compile_features(jsoncpp_lib PUBLIC
list(APPEND REQUIRED_FEATURES
cxx_std_11 # Compiler mode is aware of C++ 11.
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
@ -141,14 +115,106 @@ target_compile_features(jsoncpp_lib PUBLIC
cxx_variadic_templates # Variadic templates, as defined in N2242.
)
install( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories( jsoncpp_lib PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>)
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions(JSON_DLL_BUILD)
else()
add_definitions(-DJSON_DLL_BUILD)
endif()
set(SHARED_LIB ${PROJECT_NAME}_lib)
add_library(${SHARED_LIB} SHARED ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
set_target_properties(${SHARED_LIB} PROPERTIES
OUTPUT_NAME jsoncpp
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}
POSITION_INDEPENDENT_CODE ON
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${SHARED_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${SHARED_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${SHARED_LIB})
endif()
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
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
set(STATIC_SUFFIX "_static")
endif()
set_target_properties(${STATIC_LIB} PROPERTIES
OUTPUT_NAME jsoncpp${STATIC_SUFFIX}
VERSION ${PROJECT_VERSION}
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${STATIC_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${STATIC_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${STATIC_LIB})
endif()
if(BUILD_OBJECT_LIBS)
set(OBJECT_LIB ${PROJECT_NAME}_object)
add_library(${OBJECT_LIB} OBJECT ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
set_target_properties(${OBJECT_LIB} PROPERTIES
OUTPUT_NAME jsoncpp
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}
POSITION_INDEPENDENT_CODE ON
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${OBJECT_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${OBJECT_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${OBJECT_LIB})
endif()
install(TARGETS ${CMAKE_TARGETS} ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

View File

@ -10,6 +10,7 @@
#include <json/reader.h>
#include <json/value.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
@ -54,7 +55,7 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using CharReaderPtr = std::unique_ptr<CharReader>;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
using CharReaderPtr = std::auto_ptr<CharReader>;
#endif
// Implementation of class Features
@ -77,10 +78,7 @@ Features Features::strictMode() {
// ////////////////////////////////
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
return false;
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
}
// Class Reader
@ -464,7 +462,7 @@ bool Reader::readObject(Token& token) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
name = String(numberName.asCString());
name = numberName.asString();
} else {
break;
}
@ -629,7 +627,7 @@ bool Reader::decodeString(Token& token, String& decoded) {
Char c = *current++;
if (c == '"')
break;
else if (c == '\\') {
if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@ -863,6 +861,7 @@ class OurFeatures {
public:
static OurFeatures all();
bool allowComments_;
bool allowTrailingCommas_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_;
@ -870,6 +869,7 @@ public:
bool failIfExtra_;
bool rejectDupKeys_;
bool allowSpecialFloats_;
bool skipBom_;
size_t stackLimit_;
}; // OurFeatures
@ -938,6 +938,7 @@ private:
bool readToken(Token& token);
void skipSpaces();
void skipBom(bool skipBom);
bool match(const Char* pattern, int patternLength);
bool readComment();
bool readCStyleComment(bool* containsNewLineResult);
@ -995,10 +996,7 @@ private:
bool OurReader::containsNewLine(OurReader::Location begin,
OurReader::Location end) {
for (; begin < end; ++begin)
if (*begin == '\n' || *begin == '\r')
return true;
return false;
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
}
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
@ -1021,6 +1019,8 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
nodes_.pop();
nodes_.push(&root);
// skip byte order mark if it exists at the beginning of the UTF-8 text.
skipBom(features_.skipBom_);
bool successful = readValue();
nodes_.pop();
Token token;
@ -1175,8 +1175,11 @@ bool OurReader::readToken(Token& token) {
if (features_.allowSingleQuotes_) {
token.type_ = tokenString;
ok = readStringSingleQuote();
break;
} // else fall through
} else {
// If we don't allow single quotes, this is a failure case.
ok = false;
}
break;
case '/':
token.type_ = tokenComment;
ok = readComment();
@ -1267,6 +1270,16 @@ void OurReader::skipSpaces() {
}
}
void OurReader::skipBom(bool skipBom) {
// The default behavior is to skip BOM.
if (skipBom) {
if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
begin_ += 3;
current_ = begin_;
}
}
}
bool OurReader::match(const Char* pattern, int patternLength) {
if (end_ - current_ < patternLength)
return false;
@ -1349,11 +1362,10 @@ bool OurReader::readCStyleComment(bool* containsNewLineResult) {
while ((current_ + 1) < end_) {
Char c = getNextChar();
if (c == '*' && *current_ == '/') {
if (c == '*' && *current_ == '/')
break;
} else if (c == '\n') {
if (c == '\n')
*containsNewLineResult = true;
}
}
return getNextChar() == '/';
@ -1437,7 +1449,9 @@ bool OurReader::readObject(Token& token) {
initialTokenOk = readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
if (tokenName.type_ == tokenObjectEnd &&
(name.empty() ||
features_.allowTrailingCommas_)) // empty object or trailing comma
return true;
name.clear();
if (tokenName.type_ == tokenString) {
@ -1491,15 +1505,19 @@ bool OurReader::readArray(Token& token) {
Value init(arrayValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(token.start_ - begin_);
skipSpaces();
if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
return true;
}
int index = 0;
for (;;) {
skipSpaces();
if (current_ != end_ && *current_ == ']' &&
(index == 0 ||
(features_.allowTrailingCommas_ &&
!features_.allowDroppedNullPlaceholders_))) // empty array or trailing
// comma
{
Token endArray;
readToken(endArray);
return true;
}
Value& value = currentValue()[index++];
nodes_.push(&value);
bool ok = readValue();
@ -1571,9 +1589,9 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
// then take the inverse. This assumes that minLargestInt is only a single
// power of 10 different in magnitude, which we check above. For the last
// digit, we take the modulus before negating for the same reason.
static constexpr Value::LargestUInt negative_threshold =
static constexpr auto negative_threshold =
Value::LargestUInt(-(Value::minLargestInt / 10));
static constexpr Value::UInt negative_last_digit =
static constexpr auto negative_last_digit =
Value::UInt(-(Value::minLargestInt % 10));
const Value::LargestUInt threshold =
@ -1587,7 +1605,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
const Value::UInt digit(static_cast<Value::UInt>(c - '0'));
const auto 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, meaing value == threshold,
@ -1604,7 +1622,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
if (isNegative) {
// We use the same magnitude assumption here, just in case.
const Value::UInt last_digit = static_cast<Value::UInt>(value % 10);
const auto last_digit = static_cast<Value::UInt>(value % 10);
decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
decoded = Value::LargestInt(value);
@ -1654,9 +1672,9 @@ bool OurReader::decodeString(Token& token, String& decoded) {
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
Char c = *current++;
if (c == '"') {
if (c == '"')
break;
} else if (c == '\\') {
if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@ -1866,6 +1884,7 @@ CharReader* CharReaderBuilder::newCharReader() const {
bool collectComments = settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
features.allowComments_ = settings_["allowComments"].asBool();
features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
features.strictRoot_ = settings_["strictRoot"].asBool();
features.allowDroppedNullPlaceholders_ =
settings_["allowDroppedNullPlaceholders"].asBool();
@ -1878,38 +1897,37 @@ CharReader* CharReaderBuilder::newCharReader() const {
features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
features.skipBom_ = settings_["skipBom"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<String>* valid_keys) {
valid_keys->clear();
valid_keys->insert("collectComments");
valid_keys->insert("allowComments");
valid_keys->insert("strictRoot");
valid_keys->insert("allowDroppedNullPlaceholders");
valid_keys->insert("allowNumericKeys");
valid_keys->insert("allowSingleQuotes");
valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
valid_keys->insert("rejectDupKeys");
valid_keys->insert("allowSpecialFloats");
}
bool CharReaderBuilder::validate(Json::Value* invalid) const {
Json::Value my_invalid;
if (!invalid)
invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<String> valid_keys;
getValidReaderKeys(&valid_keys);
Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
String const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
inv[key] = settings_[key];
}
static const auto& valid_keys = *new std::set<String>{
"collectComments",
"allowComments",
"allowTrailingCommas",
"strictRoot",
"allowDroppedNullPlaceholders",
"allowNumericKeys",
"allowSingleQuotes",
"stackLimit",
"failIfExtra",
"rejectDupKeys",
"allowSpecialFloats",
"skipBom",
};
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
auto key = si.name();
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
else
return false;
}
return inv.empty();
return invalid ? invalid->empty() : true;
}
Value& CharReaderBuilder::operator[](const String& key) {
return settings_[key];
}
@ -1917,6 +1935,7 @@ Value& CharReaderBuilder::operator[](const String& key) {
void CharReaderBuilder::strictMode(Json::Value* settings) {
//! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
(*settings)["allowTrailingCommas"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@ -1925,6 +1944,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderStrictMode]
}
// static
@ -1932,6 +1952,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
//! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true;
(*settings)["allowComments"] = true;
(*settings)["allowTrailingCommas"] = true;
(*settings)["strictRoot"] = false;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@ -1940,6 +1961,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderDefaults]
}

View File

@ -71,7 +71,7 @@ enum {
};
// Defines a char buffer for use with uintToString().
typedef char UIntToStringBuffer[uintToStringBufferSize];
using UIntToStringBuffer = char[uintToStringBufferSize];
/** Converts an unsigned integer to string.
* @param value Unsigned integer to convert to string

View File

@ -8,16 +8,14 @@
#include <json/value.h>
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <sstream>
#include <utility>
#ifdef JSON_USE_CPPTL
#include <cpptl/conststring.h>
#endif
#include <algorithm> // min()
#include <cstddef> // size_t
// Provide implementation equivalent of std::snprintf for older _MSC compilers
#if defined(_MSC_VER) && _MSC_VER < 1900
@ -120,7 +118,7 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
if (length >= static_cast<size_t>(Value::maxInt))
length = Value::maxInt - 1;
char* newString = static_cast<char*>(malloc(length + 1));
auto newString = static_cast<char*>(malloc(length + 1));
if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer");
@ -140,8 +138,8 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
char* newString = static_cast<char*>(malloc(actualLength));
size_t actualLength = sizeof(length) + length + 1;
auto newString = static_cast<char*>(malloc(actualLength));
if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer");
@ -203,8 +201,8 @@ namespace Json {
#if JSON_USE_EXCEPTION
Exception::Exception(String msg) : msg_(std::move(msg)) {}
Exception::~Exception() JSONCPP_NOEXCEPT = default;
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
Exception::~Exception() noexcept = default;
char const* Exception::what() const noexcept { return msg_.c_str(); }
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
LogicError::LogicError(String const& msg) : Exception(msg) {}
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
@ -214,8 +212,14 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
throw LogicError(msg);
}
#else // !JSON_USE_EXCEPTION
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { abort(); }
JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
JSONCPP_NORETURN void throwLogicError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
#endif
// //////////////////////////////////////////////////////////////////
@ -419,14 +423,6 @@ Value::Value(const StaticString& value) {
value_.string_ = const_cast<char*>(value.c_str());
}
#ifdef JSON_USE_CPPTL
Value::Value(const CppTL::ConstString& value) {
initBasic(stringValue, true);
value_.string_ = duplicateAndPrefixStringValue(
value, static_cast<unsigned>(value.length()));
}
#endif
Value::Value(bool value) {
initBasic(booleanValue);
value_.bool_ = value;
@ -529,9 +525,10 @@ bool Value::operator<(const Value& other) const {
}
case arrayValue:
case objectValue: {
int delta = int(value_.map_->size() - other.value_.map_->size());
if (delta)
return delta < 0;
auto thisSize = value_.map_->size();
auto otherSize = other.value_.map_->size();
if (thisSize != otherSize)
return thisSize < otherSize;
return (*value_.map_) < (*other.value_.map_);
}
default:
@ -654,15 +651,6 @@ String Value::asString() const {
}
}
#ifdef JSON_USE_CPPTL
CppTL::ConstString Value::asConstString() const {
unsigned len;
char const* str;
decodePrefixedString(isAllocated(), value_.string_, &len, &str);
return CppTL::ConstString(str, len);
}
#endif
Value::Int Value::asInt() const {
switch (type()) {
case intValue:
@ -894,8 +882,7 @@ ArrayIndex Value::size() const {
bool Value::empty() const {
if (isNull() || isArray() || isObject())
return size() == 0U;
else
return false;
return false;
}
Value::operator bool() const { return !isNull(); }
@ -1135,18 +1122,6 @@ Value& Value::operator[](const StaticString& key) {
return resolveReference(key.c_str());
}
#ifdef JSON_USE_CPPTL
Value& Value::operator[](const CppTL::ConstString& key) {
return resolveReference(key.c_str(), key.end_c_str());
}
Value const& Value::operator[](CppTL::ConstString const& key) const {
Value const* found = find(key.c_str(), key.end_c_str());
if (!found)
return nullSingleton();
return *found;
}
#endif
Value& Value::append(const Value& value) { return append(Value(value)); }
Value& Value::append(Value&& value) {
@ -1158,19 +1133,22 @@ Value& Value::append(Value&& value) {
return this->value_.map_->emplace(size(), std::move(value)).first->second;
}
bool Value::insert(ArrayIndex index, Value newValue) {
bool Value::insert(ArrayIndex index, const Value& newValue) {
return insert(index, Value(newValue));
}
bool Value::insert(ArrayIndex index, Value&& newValue) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::insert: requires arrayValue");
ArrayIndex length = size();
if (index > length) {
return false;
} else {
for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = std::move((*this)[i - 1]);
}
(*this)[index] = std::move(newValue);
return true;
}
for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = std::move((*this)[i - 1]);
}
(*this)[index] = std::move(newValue);
return true;
}
Value Value::get(char const* begin, char const* end,
@ -1240,13 +1218,6 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
return true;
}
#ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key,
const Value& defaultValue) const {
return get(key.c_str(), key.end_c_str(), defaultValue);
}
#endif
bool Value::isMember(char const* begin, char const* end) const {
Value const* value = find(begin, end);
return nullptr != value;
@ -1258,12 +1229,6 @@ bool Value::isMember(String const& key) const {
return isMember(key.data(), key.data() + key.length());
}
#ifdef JSON_USE_CPPTL
bool Value::isMember(const CppTL::ConstString& key) const {
return isMember(key.c_str(), key.end_c_str());
}
#endif
Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
@ -1279,31 +1244,6 @@ Value::Members Value::getMemberNames() const {
}
return members;
}
//
//# ifdef JSON_USE_CPPTL
// EnumMemberNames
// Value::enumMemberNames() const
//{
// if ( type() == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
// MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
//
//
// EnumValues
// Value::enumValues() const
//{
// if ( type() == objectValue || type() == arrayValue )
// return CppTL::Enum::anyValues( *(value_.map_),
// CppTL::Type<const Value &>() );
// return EnumValues();
//}
//
//# endif
static bool IsIntegral(double d) {
double integral_part;

View File

@ -30,9 +30,6 @@ void ValueIteratorBase::decrement() { --current_; }
ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance(const SelfType& other) const {
#ifdef JSON_USE_CPPTL_SMALLMAP
return other.current_ - current_;
#else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance
@ -53,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
++myDistance;
}
return myDistance;
#endif
}
bool ValueIteratorBase::isEqual(const SelfType& other) const {

View File

@ -7,7 +7,9 @@
#include "json_tool.h"
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
#include <cctype>
#include <cstring>
#include <iomanip>
#include <memory>
@ -86,7 +88,7 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
using StreamWriterPtr = std::auto_ptr<StreamWriter>;
#endif
String valueToString(LargestInt value) {
@ -173,16 +175,12 @@ String valueToString(double value, unsigned int precision,
String valueToString(bool value) { return value ? "true" : "false"; }
static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
assert(s || !n);
char const* const end = s + n;
for (char const* cur = s; cur < end; ++cur) {
if (*cur == '\\' || *cur == '\"' || *cur < ' ' ||
static_cast<unsigned char>(*cur) < 0x80)
return true;
}
return false;
return std::any_of(s, s + n, [](unsigned char c) {
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
});
}
static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
@ -264,12 +262,20 @@ static String toHex16Bit(unsigned int x) {
return result;
}
static void appendRaw(String& result, unsigned ch) {
result += static_cast<char>(ch);
}
static void appendHex(String& result, unsigned ch) {
result.append("\\u").append(toHex16Bit(ch));
}
static String valueToQuotedStringN(const char* value, unsigned length,
bool emitUTF8 = false) {
if (value == nullptr)
return "";
if (!isAnyCharRequiredQuoting(value, length))
if (!doesAnyCharRequireEscaping(value, length))
return String("\"") + value + "\"";
// We have to walk value and escape any special characters.
// Appending to String is not efficient, but this should be rare.
@ -312,29 +318,26 @@ static String valueToQuotedStringN(const char* value, unsigned length,
// sequence from occurring.
default: {
if (emitUTF8) {
result += *c;
unsigned codepoint = static_cast<unsigned char>(*c);
if (codepoint < 0x20) {
appendHex(result, codepoint);
} else {
appendRaw(result, codepoint);
}
} else {
unsigned int codepoint = utf8ToCodepoint(c, end);
const unsigned int FIRST_NON_CONTROL_CODEPOINT = 0x20;
const unsigned int LAST_NON_CONTROL_CODEPOINT = 0x7F;
const unsigned int FIRST_SURROGATE_PAIR_CODEPOINT = 0x10000;
// don't escape non-control characters
// (short escape sequence are applied above)
if (FIRST_NON_CONTROL_CODEPOINT <= codepoint &&
codepoint <= LAST_NON_CONTROL_CODEPOINT) {
result += static_cast<char>(codepoint);
} else if (codepoint <
FIRST_SURROGATE_PAIR_CODEPOINT) { // codepoint is in Basic
// Multilingual Plane
result += "\\u";
result += toHex16Bit(codepoint);
} else { // codepoint is not in Basic Multilingual Plane
// convert to surrogate pair first
codepoint -= FIRST_SURROGATE_PAIR_CODEPOINT;
result += "\\u";
result += toHex16Bit((codepoint >> 10) + 0xD800);
result += "\\u";
result += toHex16Bit((codepoint & 0x3FF) + 0xDC00);
unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
if (codepoint < 0x20) {
appendHex(result, codepoint);
} else if (codepoint < 0x80) {
appendRaw(result, codepoint);
} else if (codepoint < 0x10000) {
// Basic Multilingual Plane
appendHex(result, codepoint);
} else {
// Extended Unicode. Encode 20 bits as a surrogate pair.
codepoint -= 0x10000;
appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
appendHex(result, 0xdc00 + (codepoint & 0x3ff));
}
}
} break;
@ -1197,34 +1200,30 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
endingLineFeedSymbol, usf, emitUTF8, pre,
precisionType);
}
static void getValidWriterKeys(std::set<String>* valid_keys) {
valid_keys->clear();
valid_keys->insert("indentation");
valid_keys->insert("commentStyle");
valid_keys->insert("enableYAMLCompatibility");
valid_keys->insert("dropNullPlaceholders");
valid_keys->insert("useSpecialFloats");
valid_keys->insert("emitUTF8");
valid_keys->insert("precision");
valid_keys->insert("precisionType");
}
bool StreamWriterBuilder::validate(Json::Value* invalid) const {
Json::Value my_invalid;
if (!invalid)
invalid = &my_invalid; // so we do not need to test for NULL
Json::Value& inv = *invalid;
std::set<String> valid_keys;
getValidWriterKeys(&valid_keys);
Value::Members keys = settings_.getMemberNames();
size_t n = keys.size();
for (size_t i = 0; i < n; ++i) {
String const& key = keys[i];
if (valid_keys.find(key) == valid_keys.end()) {
inv[key] = settings_[key];
}
static const auto& valid_keys = *new std::set<String>{
"indentation",
"commentStyle",
"enableYAMLCompatibility",
"dropNullPlaceholders",
"useSpecialFloats",
"emitUTF8",
"precision",
"precisionType",
};
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
auto key = si.name();
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
else
return false;
}
return inv.empty();
return invalid ? invalid->empty() : true;
}
Value& StreamWriterBuilder::operator[](const String& key) {
return settings_[key];
}

View File

@ -1,46 +1,39 @@
# vim: et ts=4 sts=4 sw=4 tw=0
add_executable( jsoncpp_test
jsontest.cpp
jsontest.h
fuzz.cpp
fuzz.h
main.cpp
)
add_executable(jsoncpp_test
jsontest.cpp
jsontest.h
fuzz.cpp
fuzz.h
main.cpp
)
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions( -DJSON_DLL )
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions( -DJSON_DLL )
endif()
target_link_libraries(jsoncpp_test jsoncpp_lib)
else()
target_link_libraries(jsoncpp_test jsoncpp_static)
endif()
target_link_libraries(jsoncpp_test jsoncpp_lib)
# another way to solve issue #90
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
add_test(NAME jsoncpp_test
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
)
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
# 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(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 ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
else(BUILD_SHARED_LIBS)
# Just run the test executable.
add_custom_command( TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
endif()
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
add_test(NAME jsoncpp_test
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
add_custom_command(TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
)
endif()
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)

View File

@ -9,7 +9,6 @@
#include <json/config.h>
#include <json/json.h>
#include <memory>
#include <stdint.h>
#include <string>
namespace Json {
@ -40,11 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
builder.settings_["collectComments"] = hash_settings & (1 << 9);
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value root;
const char* data_str = reinterpret_cast<const char*>(data);
const auto data_str = reinterpret_cast<const char*>(data);
try {
reader->parse(data_str, data_str + size, &root, nullptr);
} catch (Json::Exception const&) {

View File

@ -267,19 +267,18 @@ bool Runner::runAllTest(bool printSummary) const {
printf("All %zu tests passed\n", count);
}
return true;
} else {
for (auto& result : failures) {
result.printFailure(count > 1);
}
if (printSummary) {
size_t const failedCount = failures.size();
size_t const passedCount = count - failedCount;
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
failedCount);
}
return false;
}
for (auto& result : failures) {
result.printFailure(count > 1);
}
if (printSummary) {
size_t const failedCount = failures.size();
size_t const passedCount = count - failedCount;
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
failedCount);
}
return false;
}
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
@ -308,7 +307,8 @@ int Runner::runCommandLine(int argc, const char* argv[]) const {
if (opt == "--list-tests") {
listTests();
return 0;
} else if (opt == "--test-auto") {
}
if (opt == "--test-auto") {
preventDialogOnCrash();
} else if (opt == "--test") {
++index;

View File

@ -42,7 +42,7 @@ public:
/// Must be a POD to allow inline initialisation without stepping
/// into the debugger.
struct PredicateContext {
typedef unsigned int Id;
using Id = unsigned int;
Id id_;
const char* file_;
unsigned int line_;
@ -102,7 +102,7 @@ private:
static Json::String indentText(const Json::String& text,
const Json::String& indent);
typedef std::deque<Failure> Failures;
using Failures = std::deque<Failure>;
Failures failures_;
Json::String name_;
PredicateContext rootPredicateNode_;
@ -129,7 +129,7 @@ private:
};
/// Function pointer type for TestCase factory
typedef TestCase* (*TestCaseFactory)();
using TestCaseFactory = TestCase* (*)();
class Runner {
public:
@ -168,7 +168,7 @@ private:
static void preventDialogOnCrash();
private:
typedef std::deque<TestCaseFactory> Factories;
using Factories = std::deque<TestCaseFactory>;
Factories tests_;
};
@ -207,7 +207,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
/// The predicate may do other assertions and be a member function of the
/// fixture.
#define JSONTEST_ASSERT_PRED(expr) \
{ \
do { \
JsonTest::PredicateContext _minitest_Context = { \
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
result_->predicateStackTail_->next_ = &_minitest_Context; \
@ -215,7 +215,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
result_->predicateStackTail_ = &_minitest_Context; \
(expr); \
result_->popPredicateContext(); \
}
} while (0)
/// \brief Asserts that two values are equals.
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
@ -230,7 +230,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
/// \brief Asserts that a given expression throws an exception
#define JSONTEST_ASSERT_THROWS(expr) \
{ \
do { \
bool _threw = false; \
try { \
expr; \
@ -240,7 +240,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
if (!_threw) \
result_->addFailure(__FILE__, __LINE__, \
"expected exception thrown: " #expr); \
}
} while (0)
/// \brief Begin a fixture test case.
#define JSONTEST_FIXTURE(FixtureType, name) \

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@
{'//this is bad JSON.'}

View File

@ -0,0 +1 @@
[1,,]

View File

@ -0,0 +1 @@
{ "count" : 1234,, }

View File

@ -0,0 +1,2 @@
.=[]
.[0]=1

View File

@ -0,0 +1 @@
[1,]

View File

@ -0,0 +1,2 @@
.={}
.count=1234

View File

@ -0,0 +1 @@
{ "count" : 1234, }

View File

@ -62,6 +62,10 @@ def safeReadFile(path):
except IOError as e:
return '<File "%s" is missing: %s>' % (path,e)
class FailError(Exception):
def __init__(self, msg):
super(Exception, self).__init__(msg)
def runAllTests(jsontest_executable_path, input_dir = None,
use_valgrind=False, with_json_checker=False,
writerClass='StyledWriter'):
@ -69,45 +73,26 @@ def runAllTests(jsontest_executable_path, input_dir = None,
input_dir = os.path.join(os.getcwd(), 'data')
tests = glob(os.path.join(input_dir, '*.json'))
if with_json_checker:
all_test_jsonchecker = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
# These tests fail with strict json support, but pass with jsoncpp extra lieniency
"""
Failure details:
* Test ../jsonchecker/fail25.json
Parsing should have failed:
[" tab character in string "]
* Test ../jsonchecker/fail13.json
Parsing should have failed:
{"Numbers cannot have leading zeroes": 013}
* Test ../jsonchecker/fail18.json
Parsing should have failed:
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
* Test ../jsonchecker/fail8.json
Parsing should have failed:
["Extra close"]]
* Test ../jsonchecker/fail7.json
Parsing should have failed:
["Comma after the close"],
* Test ../jsonchecker/fail10.json
Parsing should have failed:
{"Extra value after close": true} "misplaced quoted value"
* Test ../jsonchecker/fail27.json
Parsing should have failed:
["line
break"]
"""
known_differences_withjsonchecker = [ "fail25.json", "fail13.json", "fail18.json", "fail8.json",
"fail7.json", "fail10.json", "fail27.json" ]
test_jsonchecker = [ test for test in all_test_jsonchecker if os.path.basename(test) not in known_differences_withjsonchecker ]
all_tests = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
# These tests fail with strict json support, but pass with JsonCPP's
# extra leniency features. When adding a new exclusion to this list,
# remember to add the test's number and reasoning here:
known = ["fail{}.json".format(n) for n in [
4, 9, # fail because we allow trailing commas
7, # fails because we allow commas after close
8, # fails because we allow extra close
10, # fails because we allow extra values after close
13, # fails because we allow leading zeroes in numbers
18, # fails because we allow deeply nested values
25, # fails because we allow tab characters in strings
27, # fails because we allow string line breaks
]]
test_jsonchecker = [ test for test in all_tests
if os.path.basename(test) not in known]
else:
test_jsonchecker = []
failed_tests = []
valgrind_path = use_valgrind and VALGRIND_CMD or ''
for input_path in tests + test_jsonchecker:
@ -161,10 +146,9 @@ def runAllTests(jsontest_executable_path, input_dir = None,
print()
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
len(failed_tests)))
return 1
raise FailError(repr(failed_tests))
else:
print('All %d tests passed.' % len(tests))
return 0
def main():
from optparse import OptionParser
@ -187,24 +171,21 @@ def main():
input_path = os.path.normpath(os.path.abspath(args[1]))
else:
input_path = None
status = runAllTests(jsontest_executable_path, input_path,
runAllTests(jsontest_executable_path, input_path,
use_valgrind=options.valgrind,
with_json_checker=options.with_json_checker,
writerClass='StyledWriter')
if status:
sys.exit(status)
status = runAllTests(jsontest_executable_path, input_path,
runAllTests(jsontest_executable_path, input_path,
use_valgrind=options.valgrind,
with_json_checker=options.with_json_checker,
writerClass='StyledStreamWriter')
if status:
sys.exit(status)
status = runAllTests(jsontest_executable_path, input_path,
runAllTests(jsontest_executable_path, input_path,
use_valgrind=options.valgrind,
with_json_checker=options.with_json_checker,
writerClass='BuiltStyledStreamWriter')
if status:
sys.exit(status)
if __name__ == '__main__':
main()
try:
main()
except FailError:
sys.exit(1)