mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 07:14:45 +02:00
Compare commits
51 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
7c186e549f | ||
![]() |
d9ffdc4bcb | ||
![]() |
d2c205206d | ||
![]() |
a4fb5db543 | ||
![]() |
d517d598a7 | ||
![]() |
e9b0b96be6 | ||
![]() |
3f0d63b5a9 | ||
![]() |
524234e479 | ||
![]() |
9abf11935c | ||
![]() |
8a5e792f20 | ||
![]() |
30eb5ce128 | ||
![]() |
12ceb01485 | ||
![]() |
edc6239f39 | ||
![]() |
5a0152ae1b | ||
![]() |
c648b0378a | ||
![]() |
a3afd74b80 | ||
![]() |
2cb16b35dc | ||
![]() |
83946a28db | ||
![]() |
91f1553f2c | ||
![]() |
5813ab1bc1 | ||
![]() |
a0b8c3ecb4 | ||
![]() |
b349221938 | ||
![]() |
9e23f66f61 | ||
![]() |
411d88fae8 | ||
![]() |
1ff6bb65a0 | ||
![]() |
8b20b7a317 | ||
![]() |
2e54e8ff1c | ||
![]() |
90ca694e46 | ||
![]() |
3beb37ea14 | ||
![]() |
dc180eb25e | ||
![]() |
a6fe8e27d8 | ||
![]() |
edf528edfa | ||
![]() |
6317f9a406 | ||
![]() |
6bc55ec35d | ||
![]() |
f11611c878 | ||
![]() |
8f7f35c5cd | ||
![]() |
7e5485ab5b | ||
![]() |
92d90250f2 | ||
![]() |
d6c4a8fb2d | ||
![]() |
a3c8642886 | ||
![]() |
2983f5a89a | ||
![]() |
a0bd9adfef | ||
![]() |
9e0d70aa66 | ||
![]() |
f200239d5b | ||
![]() |
cfc3e927fc | ||
![]() |
a481201af1 | ||
![]() |
9704cedb20 | ||
![]() |
781eec4da8 | ||
![]() |
1c8f7d8ae5 | ||
![]() |
554d961625 | ||
![]() |
01db7b7430 |
@@ -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: ''
|
WarningsAsErrors: ''
|
||||||
HeaderFilterRegex: ''
|
HeaderFilterRegex: ''
|
||||||
AnalyzeTemporaryDtors: false
|
AnalyzeTemporaryDtors: false
|
||||||
|
156
.travis.yml
156
.travis.yml
@@ -9,18 +9,18 @@ sudo: false
|
|||||||
addons:
|
addons:
|
||||||
homebrew:
|
homebrew:
|
||||||
packages:
|
packages:
|
||||||
- clang-format
|
- clang-format
|
||||||
- meson
|
- meson
|
||||||
- ninja
|
- ninja
|
||||||
update: false # do not update homebrew by default
|
update: false # do not update homebrew by default
|
||||||
apt:
|
apt:
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test
|
- ubuntu-toolchain-r-test
|
||||||
- llvm-toolchain-xenial-8
|
- llvm-toolchain-xenial-8
|
||||||
packages:
|
packages:
|
||||||
- clang-format-8
|
- clang-format-8
|
||||||
- clang-8
|
- clang-8
|
||||||
- valgrind
|
- valgrind
|
||||||
matrix:
|
matrix:
|
||||||
allow_failures:
|
allow_failures:
|
||||||
- os: osx
|
- os: osx
|
||||||
@@ -30,27 +30,74 @@ matrix:
|
|||||||
osx_image: xcode11
|
osx_image: xcode11
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env:
|
env:
|
||||||
CXX="clang++"
|
CXX="clang++"
|
||||||
CC="clang"
|
CC="clang"
|
||||||
LIB_TYPE=static
|
LIB_TYPE=static
|
||||||
BUILD_TYPE=release
|
BUILD_TYPE=release
|
||||||
|
LANGUAGE_STANDARD="11"
|
||||||
script: ./.travis_scripts/meson_builder.sh
|
script: ./.travis_scripts/meson_builder.sh
|
||||||
- name: Linux xenial clang meson static release testing
|
- name: Linux xenial clang meson static release testing
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env:
|
env:
|
||||||
CXX="clang++"
|
CXX="clang++"
|
||||||
CC="clang"
|
CC="clang"
|
||||||
LIB_TYPE=static
|
LIB_TYPE=static
|
||||||
BUILD_TYPE=release
|
BUILD_TYPE=release
|
||||||
|
LANGUAGE_STANDARD="11"
|
||||||
# before_install and install steps only needed for linux meson builds
|
# before_install and install steps only needed for linux meson builds
|
||||||
before_install:
|
before_install:
|
||||||
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
|
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
|
||||||
install:
|
install:
|
||||||
- source ./.travis_scripts/travis.install.${TRAVIS_OS_NAME}.sh
|
- source ./.travis_scripts/travis.install.${TRAVIS_OS_NAME}.sh
|
||||||
script: ./.travis_scripts/meson_builder.sh
|
script: ./.travis_scripts/meson_builder.sh
|
||||||
- name: Linux xenial gcc cmake coverage
|
- name: Linux xenial gcc-4.6 meson static release with C++03 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.6
|
||||||
|
env:
|
||||||
|
CC=gcc-4.6
|
||||||
|
CXX=g++-4.6
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
LANGUAGE_STANDARD="03"
|
||||||
|
# before_install and install steps only needed for linux meson builds
|
||||||
|
before_install:
|
||||||
|
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
|
||||||
|
install:
|
||||||
|
- source ./.travis_scripts/travis.install.${TRAVIS_OS_NAME}.sh
|
||||||
|
script: ./.travis_scripts/meson_builder.sh
|
||||||
|
- name: Linux xenial gcc-4.6 meson static release with C++98 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.6
|
||||||
|
env:
|
||||||
|
CC=gcc-4.6
|
||||||
|
CXX=g++-4.6
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
LANGUAGE_STANDARD="98"
|
||||||
|
# before_install and install steps only needed for linux meson builds
|
||||||
|
before_install:
|
||||||
|
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
|
||||||
|
install:
|
||||||
|
- source ./.travis_scripts/travis.install.${TRAVIS_OS_NAME}.sh
|
||||||
|
script: ./.travis_scripts/meson_builder.sh
|
||||||
|
|
||||||
|
- name: Linux xenial gcc-5.4 cmake-3.12 coverage
|
||||||
os: linux
|
os: linux
|
||||||
dist: xenial
|
dist: xenial
|
||||||
compiler: gcc
|
compiler: gcc
|
||||||
@@ -62,10 +109,77 @@ matrix:
|
|||||||
BUILD_TYPE=Debug
|
BUILD_TYPE=Debug
|
||||||
LIB_TYPE=shared
|
LIB_TYPE=shared
|
||||||
DESTDIR=/tmp/cmake_json_cpp
|
DESTDIR=/tmp/cmake_json_cpp
|
||||||
|
LANGUAGE_STANDARD="11"
|
||||||
before_install:
|
before_install:
|
||||||
- pip install --user cpp-coveralls
|
- pip install --user cpp-coveralls
|
||||||
script: ./.travis_scripts/cmake_builder.sh
|
script: ./.travis_scripts/cmake_builder.sh
|
||||||
after_success:
|
after_success:
|
||||||
- coveralls --include src/lib_json --include include
|
- coveralls --include src/lib_json --include include
|
||||||
|
- name: Linux xenial gcc-4.6 cmake-3.12 with C++98 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: gcc
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
packages:
|
||||||
|
- g++-4.6
|
||||||
|
- valgrind
|
||||||
|
env:
|
||||||
|
CC=gcc-4.6
|
||||||
|
CXX=g++-4.6
|
||||||
|
DO_MemCheck=ON
|
||||||
|
BUILD_TOOL="Unix Makefiles"
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
DESTDIR=/tmp/cmake_json_cpp
|
||||||
|
LANGUAGE_STANDARD="98"
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update
|
||||||
|
- sudo apt-get install python3
|
||||||
|
script: ./.travis_scripts/cmake_builder.sh
|
||||||
|
- name: Linux xenial gcc-5.4 cmake-3.12 with C++98 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
CC=gcc
|
||||||
|
CXX=g++
|
||||||
|
DO_MemCheck=ON
|
||||||
|
BUILD_TOOL="Unix Makefiles"
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
DESTDIR=/tmp/cmake_json_cpp
|
||||||
|
LANGUAGE_STANDARD="98"
|
||||||
|
script: ./.travis_scripts/cmake_builder.sh
|
||||||
|
- name: Linux xenial clang cmake-3.12 with C++11 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: clang
|
||||||
|
env:
|
||||||
|
CC=clang
|
||||||
|
CXX=clang++
|
||||||
|
DO_MemCheck=ON
|
||||||
|
BUILD_TOOL="Unix Makefiles"
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
DESTDIR=/tmp/cmake_json_cpp
|
||||||
|
LANGUAGE_STANDARD="11"
|
||||||
|
script: ./.travis_scripts/cmake_builder.sh
|
||||||
|
- name: Linux xenial clang cmake-3.12 with C++98 testing
|
||||||
|
os: linux
|
||||||
|
dist: xenial
|
||||||
|
compiler: gcc
|
||||||
|
env:
|
||||||
|
CC=clang
|
||||||
|
CXX=clang++
|
||||||
|
DO_MemCheck=ON
|
||||||
|
BUILD_TOOL="Unix Makefiles"
|
||||||
|
LIB_TYPE=static
|
||||||
|
BUILD_TYPE=release
|
||||||
|
DESTDIR=/tmp/cmake_json_cpp
|
||||||
|
LANGUAGE_STANDARD="98"
|
||||||
|
script: ./.travis_scripts/cmake_builder.sh
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
|
@@ -66,7 +66,7 @@ cmake --version
|
|||||||
echo ${CXX}
|
echo ${CXX}
|
||||||
${CXX} --version
|
${CXX} --version
|
||||||
_COMPILER_NAME=`basename ${CXX}`
|
_COMPILER_NAME=`basename ${CXX}`
|
||||||
if [ "${BUILD_TYPE}" == "shared" ]; then
|
if [ "${BUILD_TYPE}" = "shared" ]; then
|
||||||
_CMAKE_BUILD_SHARED_LIBS=ON
|
_CMAKE_BUILD_SHARED_LIBS=ON
|
||||||
else
|
else
|
||||||
_CMAKE_BUILD_SHARED_LIBS=OFF
|
_CMAKE_BUILD_SHARED_LIBS=OFF
|
||||||
@@ -98,6 +98,14 @@ else
|
|||||||
export _BUILD_EXE=make
|
export _BUILD_EXE=make
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Language standard
|
||||||
|
# Set default to ON
|
||||||
|
if [ "${LANGUAGE_STANDARD}" = "98" ]; then
|
||||||
|
_BUILD_WITH_CXX_11=OFF
|
||||||
|
else
|
||||||
|
_BUILD_WITH_CXX_11=ON
|
||||||
|
fi
|
||||||
|
|
||||||
_BUILD_DIR_NAME="build-cmake_${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}_${_BUILD_EXE}"
|
_BUILD_DIR_NAME="build-cmake_${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}_${_BUILD_EXE}"
|
||||||
mkdir -p ${_BUILD_DIR_NAME}
|
mkdir -p ${_BUILD_DIR_NAME}
|
||||||
cd "${_BUILD_DIR_NAME}"
|
cd "${_BUILD_DIR_NAME}"
|
||||||
@@ -112,6 +120,7 @@ cd "${_BUILD_DIR_NAME}"
|
|||||||
-DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} \
|
-DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} \
|
||||||
-DBUILD_SHARED_LIBS:BOOL=${_CMAKE_BUILD_SHARED_LIBS} \
|
-DBUILD_SHARED_LIBS:BOOL=${_CMAKE_BUILD_SHARED_LIBS} \
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR} \
|
-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR} \
|
||||||
|
-DBUILD_WITH_CXX_11=${_BUILD_WITH_CXX_11} \
|
||||||
../
|
../
|
||||||
|
|
||||||
ctest -C ${BUILD_TYPE} -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild ${CTEST_TESTING_OPTION} -D ExperimentalSubmit
|
ctest -C ${BUILD_TYPE} -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild ${CTEST_TESTING_OPTION} -D ExperimentalSubmit
|
||||||
|
@@ -64,11 +64,15 @@ ninja --version
|
|||||||
_COMPILER_NAME=`basename ${CXX}`
|
_COMPILER_NAME=`basename ${CXX}`
|
||||||
_BUILD_DIR_NAME="build-${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}"
|
_BUILD_DIR_NAME="build-${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}"
|
||||||
|
|
||||||
|
# if LANGUAGE_STANDARD not set or null, set it to 11
|
||||||
|
_CPP_STD=${LANGUAGE_STANDARD:="11"}
|
||||||
|
|
||||||
./.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}"
|
meson --fatal-meson-warnings --werror --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . "${_BUILD_DIR_NAME}"
|
||||||
ninja -v -j 2 -C "${_BUILD_DIR_NAME}"
|
|
||||||
|
|
||||||
cd "${_BUILD_DIR_NAME}"
|
cd "${_BUILD_DIR_NAME}"
|
||||||
|
meson configure -Dcpp_std="c++${_CPP_STD}"
|
||||||
|
ninja -v -j 2 -C ./
|
||||||
meson test --no-rebuild --print-errorlogs
|
meson test --no-rebuild --print-errorlogs
|
||||||
|
|
||||||
if [ "${DESTDIR}" != "/usr/local" ]; then
|
if [ "${DESTDIR}" != "/usr/local" ]; then
|
||||||
|
2
AUTHORS
2
AUTHORS
@@ -21,6 +21,7 @@ Braden McDorman <bmcdorman@gmail.com>
|
|||||||
Brandon Myers <bmyers1788@gmail.com>
|
Brandon Myers <bmyers1788@gmail.com>
|
||||||
Brendan Drew <brendan.drew@daqri.com>
|
Brendan Drew <brendan.drew@daqri.com>
|
||||||
chason <cxchao802@gmail.com>
|
chason <cxchao802@gmail.com>
|
||||||
|
Chen Guoping chenguopingdota@163.com
|
||||||
Chris Gilling <cgilling@iparadigms.com>
|
Chris Gilling <cgilling@iparadigms.com>
|
||||||
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||||
Christopher Dunn <cdunn2001@gmail.com>
|
Christopher Dunn <cdunn2001@gmail.com>
|
||||||
@@ -97,6 +98,7 @@ selaselah <selah@outlook.com>
|
|||||||
Sergiy80 <sil2004@gmail.com>
|
Sergiy80 <sil2004@gmail.com>
|
||||||
sergzub <sergzub@gmail.com>
|
sergzub <sergzub@gmail.com>
|
||||||
Stefan Schweter <stefan@schweter.it>
|
Stefan Schweter <stefan@schweter.it>
|
||||||
|
Stefano Fiorentino <stefano.fiore84@gmail.com>
|
||||||
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
||||||
Steven Hahn <hahnse@ornl.gov>
|
Steven Hahn <hahnse@ornl.gov>
|
||||||
Stuart Eichert <stuart@fivemicro.com>
|
Stuart Eichert <stuart@fivemicro.com>
|
||||||
|
222
CMakeLists.txt
222
CMakeLists.txt
@@ -37,44 +37,63 @@ foreach(pold "") # Currently Empty
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# ==== Define language standard configurations requiring at least c++11 standard
|
# Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
|
||||||
if(CMAKE_CXX_STANDARD EQUAL "98" )
|
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||||
message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported.")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
#####
|
|
||||||
## 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)
|
|
||||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
|
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 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()
|
||||||
|
|
||||||
|
# Note: project(VERSION XX) - the VERSION here is number, but VERSION in meson is string.
|
||||||
|
# Thus, it is better to be consistent.
|
||||||
project(JSONCPP
|
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>]]]
|
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
|
# Set variable named ${VAR_NAME} to value ${VALUE}
|
||||||
|
function(set_using_dynamic_name VAR_NAME VALUE)
|
||||||
|
set( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# Extract major, minor, patch from version text
|
||||||
|
# Parse a version string "X.Y.Z" and outputs
|
||||||
|
# version parts in ${OUPUT_PREFIX}_MAJOR, _MINOR, _PATCH.
|
||||||
|
# If parse succeeds then ${OUPUT_PREFIX}_FOUND is TRUE.
|
||||||
|
macro(jsoncpp_parse_version VERSION_TEXT OUPUT_PREFIX)
|
||||||
|
set(VERSION_REGEX "[0-9]+\\.[0-9]+\\.[0-9]+(-[a-zA-Z0-9_]+)?")
|
||||||
|
if( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
|
||||||
|
string(REGEX MATCHALL "[0-9]+|-([A-Za-z0-9_]+)" VERSION_PARTS ${VERSION_TEXT})
|
||||||
|
list(GET VERSION_PARTS 0 ${OUPUT_PREFIX}_MAJOR)
|
||||||
|
list(GET VERSION_PARTS 1 ${OUPUT_PREFIX}_MINOR)
|
||||||
|
list(GET VERSION_PARTS 2 ${OUPUT_PREFIX}_PATCH)
|
||||||
|
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE )
|
||||||
|
else( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
|
||||||
|
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE )
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# 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 JSONCPP_SOVERSION!!
|
||||||
|
set( JSONCPP_VERSION 00.11.0 )
|
||||||
|
set( JSONCPP_SOVERSION 23 )
|
||||||
|
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
|
||||||
message(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
|
message(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
|
||||||
set( JSONCPP_SOVERSION 22 )
|
#if(NOT JSONCPP_VERSION_FOUND)
|
||||||
|
# message(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
|
||||||
|
#endif(NOT JSONCPP_VERSION_FOUND)
|
||||||
|
|
||||||
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
|
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
|
||||||
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
|
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
|
||||||
@@ -82,117 +101,100 @@ 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_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_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
|
||||||
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
|
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
|
||||||
|
option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
|
||||||
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF)
|
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF)
|
||||||
|
option(BUILD_WITH_CXX_11 "Build jsoncpp_lib with C++11 standard." ON)
|
||||||
|
|
||||||
# Enable runtime search path support for dynamic libraries on OSX
|
## To compatible with C++0x and C++1x
|
||||||
if(APPLE)
|
set(CMAKE_MINIMUN_CXX_STANDARD 98)
|
||||||
set(CMAKE_MACOSX_RPATH 1)
|
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(CMAKE_CXX_COMPILER "/usr/bin/g++")
|
||||||
|
execute_process(COMMAND ${CMAKE_CXX_COMPILER} -dumpversion OUTPUT_VARIABLE CXX_VERSION)
|
||||||
|
if(CXX_VERSION VERSION_GREATER 4.8.0)
|
||||||
|
if(BUILD_WITH_CXX_11)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
message(STATUS "Compiled with C++11(or newer) standard!")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_STANDARD 98)
|
||||||
|
message(STATUS "Compiled with C++0x standard!")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_STANDARD 98)
|
||||||
|
message(STATUS "Compiled with C++0x standard!")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT CMAKE_CXX_STANDARD)
|
||||||
|
if (BUILD_WITH_CXX_11)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
message(STATUS "Compiled with C++1x standard!")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_STANDARD 98)
|
||||||
|
message(STATUS "Compiled with C++0x standard!")
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Adhere to GNU filesystem layout conventions
|
# Adhere to GNU filesystem layout conventions
|
||||||
include(GNUInstallDirs)
|
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"
|
configure_file("${PROJECT_SOURCE_DIR}/version.in"
|
||||||
"${PROJECT_BINARY_DIR}/version"
|
"${PROJECT_BINARY_DIR}/version"
|
||||||
NEWLINE_STYLE UNIX )
|
NEWLINE_STYLE UNIX)
|
||||||
|
|
||||||
macro(UseCompilationWarningAsError)
|
macro(use_compilation_warning_as_error)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Only enabled in debug because some old versions of VS STL generate
|
# Only enabled in debug because some old versions of VS STL generate
|
||||||
# warnings when compiled in release configuration.
|
# warnings when compiled in release configuration.
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options($<$<CONFIG:Debug>:/WX>)
|
||||||
add_compile_options($<$<CONFIG:Debug>:/WX>)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
|
|
||||||
endif()
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Werror)
|
||||||
add_compile_options(-Werror)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
|
||||||
endif()
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO)
|
if(JSONCPP_WITH_STRICT_ISO)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
|
||||||
add_compile_options(-pedantic-errors)
|
add_compile_options(-pedantic-errors)
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# Include our configuration header
|
# Include our configuration header
|
||||||
include_directories( ${jsoncpp_SOURCE_DIR}/include )
|
include_directories(${jsoncpp_SOURCE_DIR}/include)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Only enabled in debug because some old versions of VS STL generate
|
# Only enabled in debug because some old versions of VS STL generate
|
||||||
# unreachable code warning when compiled in release configuration.
|
# unreachable code warning when compiled in release configuration.
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options($<$<CONFIG:Debug>:/W4>)
|
||||||
add_compile_options($<$<CONFIG:Debug>:/W4>)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# using regular Clang or AppleClang
|
# 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)
|
||||||
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()
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
# using GCC
|
# using GCC
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
||||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
|
|
||||||
endif()
|
|
||||||
# not yet ready for -Wsign-conversion
|
# not yet ready for -Wsign-conversion
|
||||||
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO)
|
if(JSONCPP_WITH_STRICT_ISO)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall)
|
||||||
add_compile_options(-pedantic)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
|
||||||
add_compile_options(-Werror=conversion)
|
add_compile_options(-Werror=conversion)
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||||
# using Intel compiler
|
# using Intel compiler
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
|
||||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
|
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wpedantic)
|
||||||
add_compile_options(-pedantic)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
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)
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
UseCompilationWarningAsError()
|
use_compilation_warning_as_error()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||||
@@ -205,27 +207,29 @@ if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
include (CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
install(EXPORT jsoncpp
|
install(EXPORT jsoncpp
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
||||||
FILE jsoncppConfig.cmake)
|
FILE jsoncppConfig.cmake)
|
||||||
write_basic_package_version_file ("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
||||||
VERSION ${PROJECT_VERSION}
|
VERSION ${JSONCPP_VERSION}
|
||||||
COMPATIBILITY SameMajorVersion)
|
COMPATIBILITY SameMajorVersion)
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_TESTS)
|
if(JSONCPP_WITH_TESTS)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
include(CTest)
|
include(CTest)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build the different applications
|
# Build the different applications
|
||||||
add_subdirectory( src )
|
add_subdirectory(src)
|
||||||
|
|
||||||
#install the includes
|
#install the includes
|
||||||
add_subdirectory( include )
|
add_subdirectory(include)
|
||||||
|
|
||||||
#install the example
|
#install the example
|
||||||
add_subdirectory( example )
|
if(JSONCPP_WITH_EXAMPLE)
|
||||||
|
add_subdirectory(example)
|
||||||
|
endif()
|
||||||
|
@@ -27,8 +27,13 @@ Then,
|
|||||||
#LIB_TYPE=static
|
#LIB_TYPE=static
|
||||||
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
||||||
ninja -v -C 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
|
sudo ninja install
|
||||||
|
|
||||||
## Building and testing with other build systems
|
## Building and testing with other build systems
|
||||||
|
14
README.md
14
README.md
@@ -1,11 +1,5 @@
|
|||||||
# JsonCpp
|
# JsonCpp
|
||||||
|
|
||||||
[](https://bintray.com/theirix/conan-repo/jsoncpp%3Atheirix)
|
|
||||||
[](https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE)
|
|
||||||
[](http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html)
|
|
||||||
[](https://coveralls.io/github/open-source-parsers/jsoncpp?branch=master)
|
|
||||||
|
|
||||||
|
|
||||||
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
||||||
numbers, strings, ordered sequences of values, and collections of name/value
|
numbers, strings, ordered sequences of values, and collections of name/value
|
||||||
pairs.
|
pairs.
|
||||||
@@ -17,6 +11,13 @@ serialization and deserialization to and from strings. It can also preserve
|
|||||||
existing comment in unserialization/serialization steps, making it a convenient
|
existing comment in unserialization/serialization steps, making it a convenient
|
||||||
format to store user input files.
|
format to store user input files.
|
||||||
|
|
||||||
|
## Release notes
|
||||||
|
The 00.11.z branch is a new version, its major version number `00` is to shows that it is
|
||||||
|
different from branch 0.y.z and 1.y.z. The main purpose of this branch is to give users a
|
||||||
|
third choice, that is, users can only have a copy of the code, but can build in different environments,
|
||||||
|
so it can be used with old or newer compilers.
|
||||||
|
The benefit is that users can used some new features in this new branch that introduced in 1.y.z,
|
||||||
|
but can hardly applied into 0.y.z.
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
@@ -30,6 +31,7 @@ format to store user input files.
|
|||||||
|
|
||||||
* `1.y.z` is built with C++11.
|
* `1.y.z` is built with C++11.
|
||||||
* `0.y.z` can be used with older compilers.
|
* `0.y.z` can be used with older compilers.
|
||||||
|
* `00.11.z` can be used with older compilers , with new features from `1.y.z`
|
||||||
* Major versions maintain binary-compatibility.
|
* Major versions maintain binary-compatibility.
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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("/// If defined, indicates that the source file is amalgamated")
|
||||||
header.add_text("/// to prevent private header inclusion.")
|
header.add_text("/// to prevent private header inclusion.")
|
||||||
header.add_text("#define JSON_IS_AMALGAMATION")
|
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, "config.h"))
|
||||||
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
||||||
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
||||||
|
@@ -1,29 +1,27 @@
|
|||||||
#vim: et ts =4 sts = 4 sw = 4 tw = 0
|
#vim: et ts =4 sts = 4 sw = 4 tw = 0
|
||||||
cmake_minimum_required(VERSION 3.1)
|
|
||||||
|
|
||||||
set(EXAMPLES
|
set(EXAMPLES
|
||||||
readFromString
|
readFromString
|
||||||
readFromStream
|
readFromStream
|
||||||
stringWrite
|
stringWrite
|
||||||
streamWrite
|
streamWrite
|
||||||
)
|
)
|
||||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
|
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
|
||||||
set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
|
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra ")
|
add_compile_options(-Wall -Wextra)
|
||||||
else()
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-D_SCL_SECURE_NO_WARNINGS
|
-D_SCL_SECURE_NO_WARNINGS
|
||||||
-D_CRT_SECURE_NO_WARNINGS
|
-D_CRT_SECURE_NO_WARNINGS
|
||||||
-D_WIN32_WINNT=0x601
|
-D_WIN32_WINNT=0x601
|
||||||
-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach (example ${EXAMPLES})
|
foreach(example ${EXAMPLES})
|
||||||
add_executable(${example} ${example}/${example}.cpp)
|
add_executable(${example} ${example}/${example}.cpp)
|
||||||
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(${example} jsoncpp_lib)
|
target_link_libraries(${example} jsoncpp_lib)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/** \brief Parse from stream, collect comments and capture error info.
|
/** \brief Parse from stream, collect comments and capture error info.
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/**
|
/**
|
||||||
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
||||||
@@ -10,9 +11,9 @@
|
|||||||
* 20
|
* 20
|
||||||
*/
|
*/
|
||||||
int main() {
|
int main() {
|
||||||
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
const std::string rawJson = "{\"Age\": 20, \"Name\": \"colin\"}";
|
||||||
const int rawJsonLength = static_cast<int>(rawJson.length());
|
const int rawJsonLength = static_cast<int>(rawJson.length());
|
||||||
constexpr bool shouldUseOldWay = false;
|
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||||
JSONCPP_STRING err;
|
JSONCPP_STRING err;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
|
|
||||||
@@ -21,12 +22,13 @@ int main() {
|
|||||||
reader.parse(rawJson, root);
|
reader.parse(rawJson, root);
|
||||||
} else {
|
} else {
|
||||||
Json::CharReaderBuilder builder;
|
Json::CharReaderBuilder builder;
|
||||||
const std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
||||||
&err)) {
|
&err)) {
|
||||||
std::cout << "error" << std::endl;
|
std::cout << "error" << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
const std::string name = root["Name"].asString();
|
const std::string name = root["Name"].asString();
|
||||||
const int age = root["Age"].asInt();
|
const int age = root["Age"].asInt();
|
||||||
|
@@ -12,11 +12,11 @@
|
|||||||
int main() {
|
int main() {
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::StreamWriterBuilder builder;
|
Json::StreamWriterBuilder builder;
|
||||||
const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
Json::StreamWriter* writer(builder.newStreamWriter());
|
||||||
|
|
||||||
root["Name"] = "robin";
|
root["Name"] = "robin";
|
||||||
root["Age"] = 20;
|
root["Age"] = 20;
|
||||||
writer->write(root, &std::cout);
|
writer->write(root, &std::cout);
|
||||||
|
delete writer;
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
|
#include <cstdlib>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
/** \brief Write a Value object to a string.
|
/** \brief Write a Value object to a string.
|
||||||
* Example Usage:
|
* Example Usage:
|
||||||
@@ -15,7 +16,7 @@
|
|||||||
int main() {
|
int main() {
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
Json::Value data;
|
Json::Value data;
|
||||||
constexpr bool shouldUseOldWay = false;
|
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||||
root["action"] = "run";
|
root["action"] = "run";
|
||||||
data["number"] = 1;
|
data["number"] = 1;
|
||||||
root["data"] = data;
|
root["data"] = data;
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
||||||
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#define JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -86,4 +86,4 @@ bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#endif // JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#ifndef JSON_ASSERTIONS_H_INCLUDED
|
||||||
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#define JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -21,19 +21,19 @@
|
|||||||
|
|
||||||
// @todo <= add detail about condition in exception
|
// @todo <= add detail about condition in exception
|
||||||
#define JSON_ASSERT(condition) \
|
#define JSON_ASSERT(condition) \
|
||||||
{ \
|
do { \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
Json::throwLogicError("assert json failed"); \
|
Json::throwLogicError("assert json failed"); \
|
||||||
} \
|
} \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
#define JSON_FAIL_MESSAGE(message) \
|
#define JSON_FAIL_MESSAGE(message) \
|
||||||
{ \
|
do { \
|
||||||
OStringStream oss; \
|
OStringStream oss; \
|
||||||
oss << message; \
|
oss << message; \
|
||||||
Json::throwLogicError(oss.str()); \
|
Json::throwLogicError(oss.str()); \
|
||||||
abort(); \
|
abort(); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
#else // JSON_USE_EXCEPTION
|
#else // JSON_USE_EXCEPTION
|
||||||
|
|
||||||
@@ -52,8 +52,16 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JSON_ASSERT_MESSAGE(condition, message) \
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
if (!(condition)) { \
|
do { \
|
||||||
JSON_FAIL_MESSAGE(message); \
|
if (!(condition)) { \
|
||||||
}
|
JSON_FAIL_MESSAGE(message); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#define JSONCPP_STATIC_ASSERT static_assert
|
||||||
|
#else
|
||||||
|
#define JSONCPP_STATIC_ASSERT JSON_ASSERT_MESSAGE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
@@ -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
|
|
@@ -5,24 +5,20 @@
|
|||||||
|
|
||||||
#ifndef JSON_CONFIG_H_INCLUDED
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
#define JSON_CONFIG_H_INCLUDED
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
#include <cstddef>
|
|
||||||
#include <cstdint>
|
|
||||||
#include <istream>
|
#include <istream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
/// If defined, indicates that json library is embedded in CppTL library.
|
#if JSONCPP_CXX_STD_11
|
||||||
//# define JSON_IN_CPPTL 1
|
#include <cstddef> // typedef ptrdiff_t
|
||||||
|
#include <cstdint> // typedef int64_t, uint64_t
|
||||||
/// If defined, indicates that json may leverage CppTL library
|
#else
|
||||||
//# define JSON_USE_CPPTL 1
|
#include <stddef.h>
|
||||||
/// If defined, indicates that cpptl vector based map should be used instead of
|
#include <stdint.h>
|
||||||
/// std::map
|
#endif
|
||||||
/// as Value container.
|
|
||||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
|
||||||
|
|
||||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
// assertion macros. The default is to use exceptions.
|
// assertion macros. The default is to use exceptions.
|
||||||
@@ -40,37 +36,26 @@
|
|||||||
/// Remarks: it is automatically defined in the generated amalgamated header.
|
/// Remarks: it is automatically defined in the generated amalgamated header.
|
||||||
// #define JSON_IS_AMALGAMATION
|
// #define JSON_IS_AMALGAMATION
|
||||||
|
|
||||||
#ifdef JSON_IN_CPPTL
|
// Export macros for DLL visibility
|
||||||
#include <cpptl/config.h>
|
#if defined(JSON_DLL_BUILD)
|
||||||
#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)
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllexport)
|
#define JSON_API __declspec(dllexport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
#define JSON_API __attribute__((visibility("default")))
|
#define JSON_API __attribute__((visibility("default")))
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
#elif defined(JSON_DLL)
|
#elif defined(JSON_DLL)
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllimport)
|
#define JSON_API __declspec(dllimport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
#endif // ifdef JSON_IN_CPPTL
|
#endif // ifdef JSON_DLL_BUILD
|
||||||
|
|
||||||
#if !defined(JSON_API)
|
#if !defined(JSON_API)
|
||||||
#define JSON_API
|
#define JSON_API
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1800
|
|
||||||
#error \
|
|
||||||
"ERROR: Visual Studio 12 (2013) with _MSC_VER=1800 is the oldest supported compiler with sufficient C++11 capabilities"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
// As recommended at
|
// As recommended at
|
||||||
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
// https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
|
||||||
@@ -86,24 +71,41 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
// Storages, and 64 bits integer support is disabled.
|
// Storages, and 64 bits integer support is disabled.
|
||||||
// #define JSON_NO_INT64 1
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
|
#if __cplusplus >= 201103L || defined(_MSC_VER)
|
||||||
// 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
|
#define JSONCPP_OP_EXPLICIT explicit
|
||||||
#else
|
#else
|
||||||
#define JSONCPP_NOEXCEPT throw()
|
|
||||||
#define JSONCPP_OP_EXPLICIT
|
#define JSONCPP_OP_EXPLICIT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// These Macros are maintained for backwards compatibility of external tools.
|
||||||
|
#if (defined(_MSC_VER) && _MSC_VER >= 1900) || \
|
||||||
|
(defined(__GNUC__) && __cplusplus >= 201103L) || \
|
||||||
|
(defined(__clang__) && __clang_major__ == 3 && __clang_minor__ >= 3)
|
||||||
|
|
||||||
|
#define JSONCPP_CXX_STD_11 1
|
||||||
|
#else
|
||||||
|
#define JSONCPP_CXX_STD_11 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#define JSONCPP_NULL nullptr
|
||||||
|
#define JSONCPP_CONST constexpr
|
||||||
|
#define JSONCPP_CTOR_DELETE = delete
|
||||||
|
#define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#define JSONCPP_OVERRIDE override
|
||||||
|
#define JSONCPP_MOVE(value) std::move(value)
|
||||||
|
#else
|
||||||
|
#define JSONCPP_NULL NULL
|
||||||
|
#define JSONCPP_CONST const
|
||||||
|
#define JSONCPP_CTOR_DELETE
|
||||||
|
#define JSONCPP_NOEXCEPT throw()
|
||||||
|
#define JSONCPP_OVERRIDE
|
||||||
|
#define JSONCPP_MOVE(value) value
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define *deprecated* attribute
|
||||||
|
// [[deprecated]] is in C++14 or in Visual Studio 2015 and later
|
||||||
|
// For compatibility, [[deprecated]] is not used
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#if __has_extension(attribute_deprecated_with_message)
|
#if __has_extension(attribute_deprecated_with_message)
|
||||||
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
@@ -128,13 +130,15 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
#include "allocator.h"
|
#include "allocator.h"
|
||||||
|
#endif
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
typedef int Int;
|
typedef int Int;
|
||||||
typedef unsigned int UInt;
|
typedef unsigned int UInt;
|
||||||
#if defined(JSON_NO_INT64)
|
#if defined(JSON_NO_INT64)
|
||||||
@@ -155,6 +159,7 @@ typedef UInt64 LargestUInt;
|
|||||||
#define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
#endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Allocator =
|
using Allocator =
|
||||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
||||||
@@ -168,13 +173,20 @@ using OStringStream =
|
|||||||
String::allocator_type>;
|
String::allocator_type>;
|
||||||
using IStream = std::istream;
|
using IStream = std::istream;
|
||||||
using OStream = std::ostream;
|
using OStream = std::ostream;
|
||||||
|
#else
|
||||||
|
typedef std::string String;
|
||||||
|
typedef std::istringstream IStringStream;
|
||||||
|
typedef std::ostringstream OStringStream;
|
||||||
|
typedef std::istream IStream;
|
||||||
|
typedef std::ostream OStream;
|
||||||
|
#endif // JSONCPP_CXX_STD_11
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
// Legacy names (formerly macros).
|
// Legacy names (formerly macros).
|
||||||
using JSONCPP_STRING = Json::String;
|
typedef Json::String JSONCPP_STRING;
|
||||||
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
|
typedef Json::IStringStream JSONCPP_ISTRINGSTREAM;
|
||||||
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
|
typedef Json::OStringStream JSONCPP_OSTRINGSTREAM;
|
||||||
using JSONCPP_ISTREAM = Json::IStream;
|
typedef Json::IStream JSONCPP_ISTREAM;
|
||||||
using JSONCPP_OSTREAM = Json::OStream;
|
typedef Json::OStream JSONCPP_OSTREAM;
|
||||||
|
|
||||||
#endif // JSON_CONFIG_H_INCLUDED
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#ifndef JSON_JSON_H_INCLUDED
|
#ifndef JSON_JSON_H_INCLUDED
|
||||||
#define JSON_JSON_H_INCLUDED
|
#define JSON_JSON_H_INCLUDED
|
||||||
|
|
||||||
#include "autolink.h"
|
#include "config.h"
|
||||||
#include "json_features.h"
|
#include "json_features.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
#ifndef JSON_FEATURES_H_INCLUDED
|
||||||
#define CPPTL_JSON_FEATURES_H_INCLUDED
|
#define JSON_FEATURES_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
@@ -41,21 +41,21 @@ public:
|
|||||||
Features();
|
Features();
|
||||||
|
|
||||||
/// \c true if comments are allowed. Default: \c true.
|
/// \c true if comments are allowed. Default: \c true.
|
||||||
bool allowComments_{true};
|
bool allowComments_;
|
||||||
|
|
||||||
/// \c true if root must be either an array or an object value. Default: \c
|
/// \c true if root must be either an array or an object value. Default: \c
|
||||||
/// false.
|
/// false.
|
||||||
bool strictRoot_{false};
|
bool strictRoot_;
|
||||||
|
|
||||||
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||||
bool allowDroppedNullPlaceholders_{false};
|
bool allowDroppedNullPlaceholders_;
|
||||||
|
|
||||||
/// \c true if numeric object key are allowed. Default: \c false.
|
/// \c true if numeric object key are allowed. Default: \c false.
|
||||||
bool allowNumericKeys_{false};
|
bool allowNumericKeys_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
#endif // JSON_FEATURES_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
#ifndef JSON_READER_H_INCLUDED
|
||||||
#define CPPTL_JSON_READER_H_INCLUDED
|
#define JSON_READER_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "json_features.h"
|
#include "json_features.h"
|
||||||
@@ -210,7 +210,8 @@ private:
|
|||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||||
Location end, unsigned int& unicode);
|
Location end, unsigned int& unicode);
|
||||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
bool addError(const String& message, Token& token,
|
||||||
|
Location extra = JSONCPP_NULL);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const String& message, Token& token,
|
bool addErrorAndRecover(const String& message, Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
@@ -230,21 +231,21 @@ private:
|
|||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
String document_;
|
String document_;
|
||||||
Location begin_{};
|
Location begin_;
|
||||||
Location end_{};
|
Location end_;
|
||||||
Location current_{};
|
Location current_;
|
||||||
Location lastValueEnd_{};
|
Location lastValueEnd_;
|
||||||
Value* lastValue_{};
|
Value* lastValue_;
|
||||||
String commentsBefore_;
|
String commentsBefore_;
|
||||||
Features features_;
|
Features features_;
|
||||||
bool collectComments_{};
|
bool collectComments_;
|
||||||
}; // Reader
|
}; // Reader
|
||||||
|
|
||||||
/** Interface for reading JSON from a char array.
|
/** Interface for reading JSON from a char array.
|
||||||
*/
|
*/
|
||||||
class JSON_API CharReader {
|
class JSON_API CharReader {
|
||||||
public:
|
public:
|
||||||
virtual ~CharReader() = default;
|
virtual ~CharReader() {}
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
* document. The document must be a UTF-8 encoded string containing the
|
* document. The document must be a UTF-8 encoded string containing the
|
||||||
* document to read.
|
* document to read.
|
||||||
@@ -266,7 +267,7 @@ public:
|
|||||||
|
|
||||||
class JSON_API Factory {
|
class JSON_API Factory {
|
||||||
public:
|
public:
|
||||||
virtual ~Factory() = default;
|
virtual ~Factory() {}
|
||||||
/** \brief Allocate a CharReader via operator new().
|
/** \brief Allocate a CharReader via operator new().
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
@@ -299,6 +300,8 @@ public:
|
|||||||
* if allowComments is false.
|
* if allowComments is false.
|
||||||
* - `"allowComments": false or true`
|
* - `"allowComments": false or true`
|
||||||
* - true if comments are allowed.
|
* - true if comments are allowed.
|
||||||
|
* - `"allowTrailingCommas": false or true`
|
||||||
|
* - true if trailing commas in objects and arrays are allowed.
|
||||||
* - `"strictRoot": false or true`
|
* - `"strictRoot": false or true`
|
||||||
* - true if root must be either an array or an object value
|
* - true if root must be either an array or an object value
|
||||||
* - `"allowDroppedNullPlaceholders": false or true`
|
* - `"allowDroppedNullPlaceholders": false or true`
|
||||||
@@ -330,9 +333,9 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
CharReaderBuilder();
|
CharReaderBuilder();
|
||||||
~CharReaderBuilder() override;
|
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
CharReader* newCharReader() const override;
|
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
@@ -398,4 +401,4 @@ JSON_API IStream& operator>>(IStream&, Value&);
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
#endif // JSON_READER_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_H_INCLUDED
|
#ifndef JSON_H_INCLUDED
|
||||||
#define CPPTL_JSON_H_INCLUDED
|
#define JSON_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
@@ -13,29 +13,47 @@
|
|||||||
// Conditional NORETURN attribute on the throw functions would:
|
// Conditional NORETURN attribute on the throw functions would:
|
||||||
// a) suppress false positives from static code analysis
|
// a) suppress false positives from static code analysis
|
||||||
// b) possibly improve optimization opportunities.
|
// b) possibly improve optimization opportunities.
|
||||||
|
// For compatibility, [[noreturn]] is not used
|
||||||
#if !defined(JSONCPP_NORETURN)
|
#if !defined(JSONCPP_NORETURN)
|
||||||
#if defined(_MSC_VER) && _MSC_VER == 1800
|
#if defined(_MSC_VER)
|
||||||
#define JSONCPP_NORETURN __declspec(noreturn)
|
#define JSONCPP_NORETURN __declspec(noreturn)
|
||||||
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
|
#define JSONCPP_NORETURN __attribute__((noreturn))
|
||||||
#else
|
#else
|
||||||
#define JSONCPP_NORETURN [[noreturn]]
|
#define JSONCPP_NORETURN
|
||||||
|
#endif
|
||||||
|
#endif // if !defined(JSONCPP_NORETURN)
|
||||||
|
|
||||||
|
// 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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#if JSONCPP_CXX_STD_11
|
||||||
|
#else
|
||||||
|
#undef JSONCPP_TEMPLATE_DELETE
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#include <string.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <memory>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#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
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
// be used by...
|
// be used by...
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
@@ -57,8 +75,8 @@ namespace Json {
|
|||||||
class JSON_API Exception : public std::exception {
|
class JSON_API Exception : public std::exception {
|
||||||
public:
|
public:
|
||||||
Exception(String msg);
|
Exception(String msg);
|
||||||
~Exception() JSONCPP_NOEXCEPT override;
|
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
char const* what() const JSONCPP_NOEXCEPT override;
|
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String msg_;
|
String msg_;
|
||||||
@@ -120,11 +138,6 @@ enum PrecisionType {
|
|||||||
decimalPlaces ///< we set max number of digits after "." in string
|
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.
|
/** \brief Lightweight wrapper to tag static string.
|
||||||
*
|
*
|
||||||
* Value constructor and objectValue member assignment takes advantage of the
|
* Value constructor and objectValue member assignment takes advantage of the
|
||||||
@@ -141,7 +154,7 @@ enum PrecisionType {
|
|||||||
*/
|
*/
|
||||||
class JSON_API StaticString {
|
class JSON_API StaticString {
|
||||||
public:
|
public:
|
||||||
explicit StaticString(const char* czstring) : c_str_(czstring) {}
|
JSONCPP_OP_EXPLICIT StaticString(const char* czstring) : c_str_(czstring) {}
|
||||||
|
|
||||||
operator const char*() const { return c_str_; }
|
operator const char*() const { return c_str_; }
|
||||||
|
|
||||||
@@ -215,34 +228,35 @@ public:
|
|||||||
static Value const& nullSingleton();
|
static Value const& nullSingleton();
|
||||||
|
|
||||||
/// Minimum signed integer value that can be stored in a Json::Value.
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestInt minLargestInt =
|
static JSONCPP_CONST LargestInt minLargestInt =
|
||||||
LargestInt(~(LargestUInt(-1) / 2));
|
LargestInt(~(LargestUInt(-1) / 2));
|
||||||
/// Maximum signed integer value that can be stored in a Json::Value.
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
|
static JSONCPP_CONST LargestInt maxLargestInt =
|
||||||
|
LargestInt(LargestUInt(-1) / 2);
|
||||||
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
||||||
static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
|
static JSONCPP_CONST LargestUInt maxLargestUInt = LargestUInt(-1);
|
||||||
|
|
||||||
/// Minimum signed int value that can be stored in a Json::Value.
|
/// Minimum signed int value that can be stored in a Json::Value.
|
||||||
static constexpr Int minInt = Int(~(UInt(-1) / 2));
|
static JSONCPP_CONST Int minInt = Int(~(UInt(-1) / 2));
|
||||||
/// Maximum signed int value that can be stored in a Json::Value.
|
/// Maximum signed int value that can be stored in a Json::Value.
|
||||||
static constexpr Int maxInt = Int(UInt(-1) / 2);
|
static JSONCPP_CONST Int maxInt = Int(UInt(-1) / 2);
|
||||||
/// Maximum unsigned int value that can be stored in a Json::Value.
|
/// Maximum unsigned int value that can be stored in a Json::Value.
|
||||||
static constexpr UInt maxUInt = UInt(-1);
|
static JSONCPP_CONST UInt maxUInt = UInt(-1);
|
||||||
|
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
static JSONCPP_CONST Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
||||||
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
static JSONCPP_CONST Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
||||||
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
||||||
static constexpr UInt64 maxUInt64 = UInt64(-1);
|
static JSONCPP_CONST UInt64 maxUInt64 = UInt64(-1);
|
||||||
#endif // defined(JSON_HAS_INT64)
|
#endif // defined(JSON_HAS_INT64)
|
||||||
/// Default precision for real value for string representation.
|
/// Default precision for real value for string representation.
|
||||||
static constexpr UInt defaultRealPrecision = 17;
|
static JSONCPP_CONST UInt defaultRealPrecision = 17;
|
||||||
// The constant is hard-coded because some compiler have trouble
|
// The constant is hard-coded because some compiler have trouble
|
||||||
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
|
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
|
||||||
// Assumes that UInt64 is a 64 bits integer.
|
// Assumes that UInt64 is a 64 bits integer.
|
||||||
static constexpr double maxUInt64AsDouble = 18446744073709551615.0;
|
static JSONCPP_CONST double maxUInt64AsDouble = 18446744073709551615.0;
|
||||||
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
|
// Workaround for bug in the NVIDIAs CUDA 9.1 nvcc compiler
|
||||||
// when using gcc and clang backend compilers. CZString
|
// when using gcc and clang backend compilers. CZString
|
||||||
// cannot be defined as private. See issue #486
|
// cannot be defined as private. See issue #486
|
||||||
@@ -258,11 +272,14 @@ private:
|
|||||||
CZString(ArrayIndex index);
|
CZString(ArrayIndex index);
|
||||||
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
CZString(CZString const& other);
|
CZString(CZString const& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
CZString(CZString&& other);
|
CZString(CZString&& other);
|
||||||
|
#endif
|
||||||
~CZString();
|
~CZString();
|
||||||
CZString& operator=(const CZString& other);
|
CZString& operator=(const CZString& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
CZString& operator=(CZString&& other);
|
CZString& operator=(CZString&& other);
|
||||||
|
#endif
|
||||||
bool operator<(CZString const& other) const;
|
bool operator<(CZString const& other) const;
|
||||||
bool operator==(CZString const& other) const;
|
bool operator==(CZString const& other) const;
|
||||||
ArrayIndex index() const;
|
ArrayIndex index() const;
|
||||||
@@ -287,11 +304,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifndef JSON_USE_CPPTL_SMALLMAP
|
|
||||||
typedef std::map<CZString, Value> ObjectValues;
|
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
|
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -340,18 +353,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
Value(const StaticString& value);
|
Value(const StaticString& value);
|
||||||
Value(const String& value);
|
Value(const String& value);
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
Value(const CppTL::ConstString& value);
|
|
||||||
#endif
|
|
||||||
Value(bool value);
|
Value(bool value);
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value(Value&& other);
|
Value(Value&& other);
|
||||||
|
#endif
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
/// \note Overwrite existing comments. To preserve comments, use
|
/// \note Overwrite existing comments. To preserve comments, use
|
||||||
/// #swapPayload().
|
/// #swapPayload().
|
||||||
Value& operator=(const Value& other);
|
Value& operator=(const Value& other);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& operator=(Value&& other);
|
Value& operator=(Value&& other);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Swap everything.
|
/// Swap everything.
|
||||||
void swap(Value& other);
|
void swap(Value& other);
|
||||||
@@ -384,9 +398,6 @@ public:
|
|||||||
* \return false if !string. (Seg-fault if str or end are NULL.)
|
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||||
*/
|
*/
|
||||||
bool getString(char const** begin, char const** end) const;
|
bool getString(char const** begin, char const** end) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
CppTL::ConstString asConstString() const;
|
|
||||||
#endif
|
|
||||||
Int asInt() const;
|
Int asInt() const;
|
||||||
UInt asUInt() const;
|
UInt asUInt() const;
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
@@ -413,8 +424,8 @@ public:
|
|||||||
bool isObject() const;
|
bool isObject() const;
|
||||||
|
|
||||||
/// The `as<T>` and `is<T>` member function templates and specializations.
|
/// The `as<T>` and `is<T>` member function templates and specializations.
|
||||||
template <typename T> T as() const = delete;
|
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
|
||||||
template <typename T> bool is() const = delete;
|
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
|
||||||
|
|
||||||
bool isConvertibleTo(ValueType other) const;
|
bool isConvertibleTo(ValueType other) const;
|
||||||
|
|
||||||
@@ -467,9 +478,15 @@ public:
|
|||||||
///
|
///
|
||||||
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||||
Value& append(const Value& value);
|
Value& append(const Value& value);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& append(Value&& value);
|
Value& append(Value&& value);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// \brief Insert value in array at specific index
|
/// \brief Insert value in array at specific index
|
||||||
bool insert(ArrayIndex index, Value newValue);
|
bool insert(ArrayIndex index, const Value& newValue);
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
|
bool insert(ArrayIndex index, Value&& newValue);
|
||||||
|
#endif
|
||||||
|
|
||||||
/// Access an object value by name, create a null member if it does not exist.
|
/// 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.
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
@@ -498,13 +515,6 @@ public:
|
|||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
Value& operator[](const StaticString& key);
|
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.
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
Value get(const char* key, const Value& defaultValue) const;
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
@@ -517,11 +527,6 @@ public:
|
|||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
Value get(const String& key, const Value& defaultValue) const;
|
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,
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
/// and operator[]const
|
/// and operator[]const
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
@@ -567,10 +572,6 @@ public:
|
|||||||
bool isMember(const String& key) const;
|
bool isMember(const String& key) const;
|
||||||
/// Same as isMember(String const& key)const
|
/// Same as isMember(String const& key)const
|
||||||
bool isMember(const char* begin, const char* end) 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.
|
/// \brief Return a list of the member names.
|
||||||
///
|
///
|
||||||
@@ -579,22 +580,13 @@ public:
|
|||||||
/// \post if type() was nullValue, it remains nullValue
|
/// \post if type() was nullValue, it remains nullValue
|
||||||
Members getMemberNames() const;
|
Members getMemberNames() const;
|
||||||
|
|
||||||
//# ifdef JSON_USE_CPPTL
|
|
||||||
// EnumMemberNames enumMemberNames() const;
|
|
||||||
// EnumValues enumValues() const;
|
|
||||||
//# endif
|
|
||||||
|
|
||||||
/// \deprecated Always pass len.
|
/// \deprecated Always pass len.
|
||||||
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
||||||
void setComment(const char* comment, CommentPlacement placement) {
|
void setComment(const char* comment, CommentPlacement placement);
|
||||||
setComment(String(comment, strlen(comment)), placement);
|
|
||||||
}
|
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(const char* comment, size_t len, CommentPlacement placement) {
|
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||||
setComment(String(comment, len), placement);
|
|
||||||
}
|
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(String comment, CommentPlacement placement);
|
void setComment(const String& comment, CommentPlacement placement);
|
||||||
bool hasComment(CommentPlacement placement) const;
|
bool hasComment(CommentPlacement placement) const;
|
||||||
/// Include delimiters and embedded newlines.
|
/// Include delimiters and embedded newlines.
|
||||||
String getComment(CommentPlacement placement) const;
|
String getComment(CommentPlacement placement) const;
|
||||||
@@ -656,18 +648,15 @@ private:
|
|||||||
|
|
||||||
class Comments {
|
class Comments {
|
||||||
public:
|
public:
|
||||||
Comments() = default;
|
Comments() {}
|
||||||
Comments(const Comments& that);
|
Comments(const Comments& that);
|
||||||
Comments(Comments&& that);
|
|
||||||
Comments& operator=(const Comments& that);
|
Comments& operator=(const Comments& that);
|
||||||
Comments& operator=(Comments&& that);
|
|
||||||
bool has(CommentPlacement slot) const;
|
bool has(CommentPlacement slot) const;
|
||||||
String get(CommentPlacement slot) const;
|
String get(CommentPlacement slot) const;
|
||||||
void set(CommentPlacement slot, String comment);
|
void set(CommentPlacement slot, String s);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using Array = std::array<String, numberOfCommentPlacement>;
|
String ptr_[numberOfCommentPlacement];
|
||||||
std::unique_ptr<Array> ptr_;
|
|
||||||
};
|
};
|
||||||
Comments comments_;
|
Comments comments_;
|
||||||
|
|
||||||
@@ -706,11 +695,6 @@ template <> inline float Value::as<float>() const { return asFloat(); }
|
|||||||
template <> inline const char* Value::as<const char*>() const {
|
template <> inline const char* Value::as<const char*>() const {
|
||||||
return asCString();
|
return asCString();
|
||||||
}
|
}
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
template <> inline CppTL::ConstString Value::as<CppTL::ConstString>() const {
|
|
||||||
return asConstString();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \brief Experimental and untested: represents an element of the "path" to
|
/** \brief Experimental and untested: represents an element of the "path" to
|
||||||
* access a node.
|
* access a node.
|
||||||
@@ -727,8 +711,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
enum Kind { kindNone = 0, kindIndex, kindKey };
|
enum Kind { kindNone = 0, kindIndex, kindKey };
|
||||||
String key_;
|
String key_;
|
||||||
ArrayIndex index_{};
|
ArrayIndex index_;
|
||||||
Kind kind_{kindNone};
|
Kind kind_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Experimental and untested: represents a "path" to access a node.
|
/** \brief Experimental and untested: represents a "path" to access a node.
|
||||||
@@ -833,13 +817,14 @@ protected:
|
|||||||
private:
|
private:
|
||||||
Value::ObjectValues::iterator current_;
|
Value::ObjectValues::iterator current_;
|
||||||
// Indicates that iterator is for a null value.
|
// Indicates that iterator is for a null value.
|
||||||
bool isNull_{true};
|
bool isNull_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// For some reason, BORLAND needs these at the end, rather
|
// For some reason, BORLAND needs these at the end, rather
|
||||||
// than earlier. No idea why.
|
// than earlier. No idea why.
|
||||||
ValueIteratorBase();
|
ValueIteratorBase();
|
||||||
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief const iterator for object and array value.
|
/** \brief const iterator for object and array value.
|
||||||
@@ -862,7 +847,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
/*! \internal Use by Value to create an iterator.
|
/*! \internal Use by Value to create an iterator.
|
||||||
*/
|
*/
|
||||||
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelfType& operator=(const ValueIteratorBase& other);
|
SelfType& operator=(const ValueIteratorBase& other);
|
||||||
@@ -908,13 +894,14 @@ public:
|
|||||||
typedef ValueIterator SelfType;
|
typedef ValueIterator SelfType;
|
||||||
|
|
||||||
ValueIterator();
|
ValueIterator();
|
||||||
explicit ValueIterator(const ValueConstIterator& other);
|
JSONCPP_OP_EXPLICIT ValueIterator(const ValueConstIterator& other);
|
||||||
ValueIterator(const ValueIterator& other);
|
ValueIterator(const ValueIterator& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*! \internal Use by Value to create an iterator.
|
/*! \internal Use by Value to create an iterator.
|
||||||
*/
|
*/
|
||||||
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
JSONCPP_OP_EXPLICIT
|
||||||
|
ValueIterator(const Value::ObjectValues::iterator& current);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SelfType& operator=(const SelfType& other);
|
SelfType& operator=(const SelfType& other);
|
||||||
@@ -960,4 +947,4 @@ inline void swap(Value& a, Value& b) { a.swap(b); }
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_H_INCLUDED
|
#endif // JSON_H_INCLUDED
|
||||||
|
@@ -9,10 +9,10 @@
|
|||||||
// 3. /CMakeLists.txt
|
// 3. /CMakeLists.txt
|
||||||
// IMPORTANT: also update the SOVERSION!!
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
#define JSONCPP_VERSION_STRING "1.9.2"
|
#define JSONCPP_VERSION_STRING "00.11.0"
|
||||||
#define JSONCPP_VERSION_MAJOR 1
|
#define JSONCPP_VERSION_MAJOR 00
|
||||||
#define JSONCPP_VERSION_MINOR 9
|
#define JSONCPP_VERSION_MINOR 11
|
||||||
#define JSONCPP_VERSION_PATCH 2
|
#define JSONCPP_VERSION_PATCH 0
|
||||||
#define JSONCPP_VERSION_QUALIFIER
|
#define JSONCPP_VERSION_QUALIFIER
|
||||||
#define JSONCPP_VERSION_HEXA \
|
#define JSONCPP_VERSION_HEXA \
|
||||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
|
@@ -119,12 +119,12 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
StreamWriterBuilder();
|
StreamWriterBuilder();
|
||||||
~StreamWriterBuilder() override;
|
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
StreamWriter* newStreamWriter() const override;
|
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
@@ -169,7 +169,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
|
|||||||
: public Writer {
|
: public Writer {
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
~FastWriter() override = default;
|
~FastWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
void enableYAMLCompatibility();
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
@@ -183,15 +183,15 @@ public:
|
|||||||
void omitEndingLineFeed();
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
String write(const Value& root) override;
|
String write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
String document_;
|
String document_;
|
||||||
bool yamlCompatibilityEnabled_{false};
|
bool yamlCompatibilityEnabled_;
|
||||||
bool dropNullPlaceholders_{false};
|
bool dropNullPlaceholders_;
|
||||||
bool omitEndingLineFeed_{false};
|
bool omitEndingLineFeed_;
|
||||||
};
|
};
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@@ -229,14 +229,14 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
|||||||
StyledWriter : public Writer {
|
StyledWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
~StyledWriter() override = default;
|
~StyledWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \return String containing the JSON document that represents the root value.
|
* \return String containing the JSON document that represents the root value.
|
||||||
*/
|
*/
|
||||||
String write(const Value& root) override;
|
String write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
@@ -257,9 +257,9 @@ private:
|
|||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
String document_;
|
String document_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
unsigned int rightMargin_{74};
|
unsigned int rightMargin_;
|
||||||
unsigned int indentSize_{3};
|
unsigned int indentSize_;
|
||||||
bool addChildValues_{false};
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
@@ -301,7 +301,7 @@ public:
|
|||||||
* \param indentation Each level will be indented by this amount extra.
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
*/
|
*/
|
||||||
StyledStreamWriter(String indentation = "\t");
|
StyledStreamWriter(String indentation = "\t");
|
||||||
~StyledStreamWriter() = default;
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
@@ -331,7 +331,7 @@ private:
|
|||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
OStream* document_;
|
OStream* document_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
unsigned int rightMargin_{74};
|
unsigned int rightMargin_;
|
||||||
String indentation_;
|
String indentation_;
|
||||||
bool addChildValues_ : 1;
|
bool addChildValues_ : 1;
|
||||||
bool indented_ : 1;
|
bool indented_ : 1;
|
||||||
@@ -348,7 +348,7 @@ String JSON_API valueToString(LargestInt value);
|
|||||||
String JSON_API valueToString(LargestUInt value);
|
String JSON_API valueToString(LargestUInt value);
|
||||||
String JSON_API valueToString(
|
String JSON_API valueToString(
|
||||||
double value, unsigned int precision = Value::defaultRealPrecision,
|
double value, unsigned int precision = Value::defaultRealPrecision,
|
||||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
PrecisionType precisionType = significantDigits);
|
||||||
String JSON_API valueToString(bool value);
|
String JSON_API valueToString(bool value);
|
||||||
String JSON_API valueToQuotedString(const char* value);
|
String JSON_API valueToQuotedString(const char* value);
|
||||||
|
|
||||||
|
48
meson.build
48
meson.build
@@ -9,7 +9,7 @@ project(
|
|||||||
# 2. /include/json/version.h
|
# 2. /include/json/version.h
|
||||||
# 3. /CMakeLists.txt
|
# 3. /CMakeLists.txt
|
||||||
# IMPORTANT: also update the SOVERSION!!
|
# IMPORTANT: also update the SOVERSION!!
|
||||||
version : '1.9.2',
|
version : '00.11.0',
|
||||||
default_options : [
|
default_options : [
|
||||||
'buildtype=release',
|
'buildtype=release',
|
||||||
'cpp_std=c++11',
|
'cpp_std=c++11',
|
||||||
@@ -18,10 +18,9 @@ project(
|
|||||||
meson_version : '>= 0.49.0')
|
meson_version : '>= 0.49.0')
|
||||||
|
|
||||||
|
|
||||||
jsoncpp_headers = [
|
jsoncpp_headers = files([
|
||||||
'include/json/allocator.h',
|
'include/json/allocator.h',
|
||||||
'include/json/assertions.h',
|
'include/json/assertions.h',
|
||||||
'include/json/autolink.h',
|
|
||||||
'include/json/config.h',
|
'include/json/config.h',
|
||||||
'include/json/json_features.h',
|
'include/json/json_features.h',
|
||||||
'include/json/forwards.h',
|
'include/json/forwards.h',
|
||||||
@@ -29,7 +28,8 @@ jsoncpp_headers = [
|
|||||||
'include/json/reader.h',
|
'include/json/reader.h',
|
||||||
'include/json/value.h',
|
'include/json/value.h',
|
||||||
'include/json/version.h',
|
'include/json/version.h',
|
||||||
'include/json/writer.h']
|
'include/json/writer.h',
|
||||||
|
])
|
||||||
jsoncpp_include_directories = include_directories('include')
|
jsoncpp_include_directories = include_directories('include')
|
||||||
|
|
||||||
install_headers(
|
install_headers(
|
||||||
@@ -45,13 +45,12 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
jsoncpp_lib = library(
|
jsoncpp_lib = library(
|
||||||
'jsoncpp',
|
'jsoncpp', files([
|
||||||
[ jsoncpp_headers,
|
|
||||||
'src/lib_json/json_tool.h',
|
|
||||||
'src/lib_json/json_reader.cpp',
|
'src/lib_json/json_reader.cpp',
|
||||||
'src/lib_json/json_value.cpp',
|
'src/lib_json/json_value.cpp',
|
||||||
'src/lib_json/json_writer.cpp'],
|
'src/lib_json/json_writer.cpp',
|
||||||
soversion : 22,
|
]),
|
||||||
|
soversion : 23,
|
||||||
install : true,
|
install : true,
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
cpp_args: dll_export_flag)
|
cpp_args: dll_export_flag)
|
||||||
@@ -67,18 +66,21 @@ import('pkgconfig').generate(
|
|||||||
jsoncpp_dep = declare_dependency(
|
jsoncpp_dep = declare_dependency(
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
link_with : jsoncpp_lib,
|
link_with : jsoncpp_lib,
|
||||||
version : meson.project_version(),
|
version : meson.project_version())
|
||||||
)
|
|
||||||
|
|
||||||
# tests
|
# tests
|
||||||
python = import('python').find_installation()
|
if meson.is_subproject() or not get_option('tests')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
python = import('python').find_installation('python3')
|
||||||
|
|
||||||
jsoncpp_test = executable(
|
jsoncpp_test = executable(
|
||||||
'jsoncpp_test',
|
'jsoncpp_test', files([
|
||||||
[ 'src/test_lib_json/jsontest.cpp',
|
'src/test_lib_json/jsontest.cpp',
|
||||||
'src/test_lib_json/jsontest.h',
|
|
||||||
'src/test_lib_json/main.cpp',
|
'src/test_lib_json/main.cpp',
|
||||||
'src/test_lib_json/fuzz.cpp'],
|
'src/test_lib_json/fuzz.cpp',
|
||||||
|
]),
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
link_with : jsoncpp_lib,
|
link_with : jsoncpp_lib,
|
||||||
install : false,
|
install : false,
|
||||||
@@ -101,5 +103,17 @@ test(
|
|||||||
'-B',
|
'-B',
|
||||||
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||||
jsontestrunner,
|
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
5
meson_options.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
option(
|
||||||
|
'tests',
|
||||||
|
type : 'boolean',
|
||||||
|
value : true,
|
||||||
|
description : 'Enable building tests')
|
@@ -1,24 +1,24 @@
|
|||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
# The new Python3 module is much more robust than the previous PythonInterp
|
# The new Python3 module is much more robust than the previous PythonInterp
|
||||||
find_package (Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
# Set variables for backwards compatibility with cmake < 3.12.0
|
# Set variables for backwards compatibility with cmake < 3.12.0
|
||||||
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
||||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
||||||
else()
|
else()
|
||||||
set(Python_ADDITIONAL_VERSIONS 3.8)
|
set(Python_ADDITIONAL_VERSIONS 3.8)
|
||||||
find_package(PythonInterp 3)
|
find_package(PythonInterp 3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(jsontestrunner_exe
|
add_executable(jsontestrunner_exe
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions( JSON_DLL )
|
add_compile_definitions( JSON_DLL )
|
||||||
else()
|
else()
|
||||||
add_definitions( -DJSON_DLL )
|
add_definitions(-DJSON_DLL)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
||||||
|
|
||||||
@@ -32,18 +32,18 @@ if(PYTHONINTERP_FOUND)
|
|||||||
# Run unit tests in post-build
|
# Run unit tests in post-build
|
||||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||||
add_custom_target(jsoncpp_readerwriter_tests
|
add_custom_target(jsoncpp_readerwriter_tests
|
||||||
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
DEPENDS jsontestrunner_exe jsoncpp_test
|
DEPENDS jsontestrunner_exe jsoncpp_test
|
||||||
)
|
)
|
||||||
add_custom_target(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
|
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
|
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
||||||
add_test(NAME jsoncpp_readerwriter
|
add_test(NAME jsoncpp_readerwriter
|
||||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||||
)
|
)
|
||||||
add_test(NAME jsoncpp_readerwriter_json_checker
|
add_test(NAME jsoncpp_readerwriter_json_checker
|
||||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -24,7 +24,9 @@ struct Options {
|
|||||||
Json::String path;
|
Json::String path;
|
||||||
Json::Features features;
|
Json::Features features;
|
||||||
bool parseOnly;
|
bool parseOnly;
|
||||||
using writeFuncType = Json::String (*)(Json::Value const&);
|
|
||||||
|
typedef Json::String (*writeFuncType)(Json::Value const&);
|
||||||
|
|
||||||
writeFuncType write;
|
writeFuncType write;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -58,10 +60,10 @@ static Json::String readInputTestFile(const char* path) {
|
|||||||
return "";
|
return "";
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
long const size = ftell(file);
|
long const size = ftell(file);
|
||||||
size_t const usize = static_cast<unsigned long>(size);
|
size_t const usize = static_cast<size_t>(size);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
char* buffer = new char[size + 1];
|
char* buffer = new char[usize + 1];
|
||||||
buffer[size] = 0;
|
buffer[usize] = 0;
|
||||||
Json::String text;
|
Json::String text;
|
||||||
if (fread(buffer, 1, usize, file) == usize)
|
if (fread(buffer, 1, usize, file) == usize)
|
||||||
text = buffer;
|
text = buffer;
|
||||||
@@ -111,7 +113,9 @@ static void printValueTree(FILE* fout, Json::Value& value,
|
|||||||
Json::Value::Members members(value.getMemberNames());
|
Json::Value::Members members(value.getMemberNames());
|
||||||
std::sort(members.begin(), members.end());
|
std::sort(members.begin(), members.end());
|
||||||
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||||
for (auto name : members) {
|
for (Json::Value::Members::const_iterator it = members.begin();
|
||||||
|
it != members.end(); it++) {
|
||||||
|
const Json::String& name = *it;
|
||||||
printValueTree(fout, value[name], path + suffix + name);
|
printValueTree(fout, value[name], path + suffix + name);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -138,7 +142,7 @@ static int parseAndSaveValueTree(const Json::String& input,
|
|||||||
features.allowDroppedNullPlaceholders_;
|
features.allowDroppedNullPlaceholders_;
|
||||||
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
||||||
|
|
||||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
Json::String errors;
|
Json::String errors;
|
||||||
const bool parsingSuccessful =
|
const bool parsingSuccessful =
|
||||||
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
||||||
@@ -148,7 +152,7 @@ static int parseAndSaveValueTree(const Json::String& input,
|
|||||||
<< errors << std::endl;
|
<< errors << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
// We may instead check the legacy implementation (to ensure it doesn't
|
// We may instead check the legacy implementation (to ensure it doesn't
|
||||||
// randomly get broken).
|
// randomly get broken).
|
||||||
} else {
|
} else {
|
||||||
|
@@ -1,13 +1,7 @@
|
|||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
|
||||||
#Get compiler version.
|
|
||||||
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
|
||||||
OUTPUT_VARIABLE GNUCXX_VERSION )
|
|
||||||
|
|
||||||
#-Werror=* was introduced -after- GCC 4.1.2
|
#-Werror=* was introduced -after- GCC 4.1.2
|
||||||
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
|
add_compile_options("-Werror=strict-aliasing")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
endif()
|
||||||
endif()
|
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
|
||||||
|
|
||||||
include(CheckIncludeFileCXX)
|
include(CheckIncludeFileCXX)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
@@ -35,15 +29,15 @@ endif()
|
|||||||
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
||||||
message(WARNING "Locale functionality is not supported")
|
message(WARNING "Locale functionality is not supported")
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
|
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
|
||||||
else()
|
else()
|
||||||
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
|
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
|
||||||
endif()
|
endif()
|
||||||
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/config.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/json_features.h
|
${JSONCPP_INCLUDE_DIR}/json/json_features.h
|
||||||
@@ -52,48 +46,51 @@ set( PUBLIC_HEADERS
|
|||||||
${JSONCPP_INCLUDE_DIR}/json/version.h
|
${JSONCPP_INCLUDE_DIR}/json/version.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group( "Public API" FILES ${PUBLIC_HEADERS} )
|
source_group("Public API" FILES ${PUBLIC_HEADERS})
|
||||||
|
|
||||||
set(jsoncpp_sources
|
set(jsoncpp_sources
|
||||||
json_tool.h
|
json_tool.h
|
||||||
json_reader.cpp
|
json_reader.cpp
|
||||||
json_valueiterator.inl
|
json_valueiterator.inl
|
||||||
json_value.cpp
|
json_value.cpp
|
||||||
json_writer.cpp)
|
json_writer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
# Install instructions for this target
|
# Install instructions for this target
|
||||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
set(INSTALL_EXPORT EXPORT jsoncpp)
|
set(INSTALL_EXPORT EXPORT jsoncpp)
|
||||||
else(JSONCPP_WITH_CMAKE_PACKAGE)
|
else()
|
||||||
set(INSTALL_EXPORT)
|
set(INSTALL_EXPORT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions( JSON_DLL_BUILD )
|
add_compile_definitions(JSON_DLL_BUILD)
|
||||||
else()
|
else()
|
||||||
add_definitions( -DJSON_DLL_BUILD )
|
add_definitions(-DJSON_DLL_BUILD)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
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
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
|
OUTPUT_NAME jsoncpp
|
||||||
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
|
VERSION ${JSONCPP_VERSION}
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
SOVERSION ${JSONCPP_SOVERSION}
|
||||||
|
POSITION_INDEPENDENT_CODE ON
|
||||||
|
)
|
||||||
|
|
||||||
# Set library's runtime search path on OSX
|
# Set library's runtime search path on OSX
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
|
set_target_properties(jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Specify compiler features required when compiling a given target.
|
# 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
|
# 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
|
# for complete list of features available
|
||||||
|
if(CMAKE_CXX_STANDARD EQUAL "11")
|
||||||
target_compile_features(jsoncpp_lib PUBLIC
|
target_compile_features(jsoncpp_lib PUBLIC
|
||||||
cxx_std_11 # Compiler mode is aware of C++ 11.
|
cxx_std_11 # Compiler mode is aware of C++ 11.
|
||||||
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
||||||
@@ -140,15 +137,21 @@ target_compile_features(jsoncpp_lib PUBLIC
|
|||||||
cxx_variadic_macros # Variadic macros, as defined in N1653.
|
cxx_variadic_macros # Variadic macros, as defined in N1653.
|
||||||
cxx_variadic_templates # Variadic templates, as defined in N2242.
|
cxx_variadic_templates # Variadic templates, as defined in N2242.
|
||||||
)
|
)
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_STANDARD 98)
|
||||||
|
target_compile_features(jsoncpp_lib PUBLIC)
|
||||||
|
endif()
|
||||||
|
|
||||||
install( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
install(TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
|
)
|
||||||
|
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||||
target_include_directories( jsoncpp_lib PUBLIC
|
target_include_directories(jsoncpp_lib PUBLIC
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>)
|
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -51,18 +51,15 @@ static size_t const stackLimit_g =
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
typedef CharReader* CharReaderPtr;
|
||||||
using CharReaderPtr = std::unique_ptr<CharReader>;
|
|
||||||
#else
|
|
||||||
typedef std::auto_ptr<CharReader> CharReaderPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Implementation of class Features
|
// Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
|
||||||
Features::Features() = default;
|
Features::Features()
|
||||||
|
: allowComments_(true), strictRoot_(false),
|
||||||
Features Features::all() { return {}; }
|
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
|
||||||
|
Features Features::all() { return Features(); }
|
||||||
|
|
||||||
Features Features::strictMode() {
|
Features Features::strictMode() {
|
||||||
Features features;
|
Features features;
|
||||||
@@ -86,9 +83,15 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
|
|||||||
// Class Reader
|
// Class Reader
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Reader::Reader() : features_(Features::all()) {}
|
Reader::Reader()
|
||||||
|
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||||
|
lastValue_(), commentsBefore_(), features_(Features::all()),
|
||||||
|
collectComments_() {}
|
||||||
|
|
||||||
Reader::Reader(const Features& features) : features_(features) {}
|
Reader::Reader(const Features& features)
|
||||||
|
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||||
|
lastValue_(), commentsBefore_(), features_(features), collectComments_() {
|
||||||
|
}
|
||||||
|
|
||||||
bool Reader::parse(const std::string& document, Value& root,
|
bool Reader::parse(const std::string& document, Value& root,
|
||||||
bool collectComments) {
|
bool collectComments) {
|
||||||
@@ -121,8 +124,8 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
end_ = endDoc;
|
end_ = endDoc;
|
||||||
collectComments_ = collectComments;
|
collectComments_ = collectComments;
|
||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = nullptr;
|
lastValueEnd_ = JSONCPP_NULL;
|
||||||
lastValue_ = nullptr;
|
lastValue_ = JSONCPP_NULL;
|
||||||
commentsBefore_.clear();
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
@@ -376,7 +379,7 @@ void Reader::addComment(Location begin, Location end,
|
|||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const String& normalized = normalizeEOL(begin, end);
|
const String& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != nullptr);
|
assert(lastValue_ != JSONCPP_NULL);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
} else {
|
} else {
|
||||||
commentsBefore_ += normalized;
|
commentsBefore_ += normalized;
|
||||||
@@ -464,7 +467,7 @@ bool Reader::readObject(Token& token) {
|
|||||||
Value numberName;
|
Value numberName;
|
||||||
if (!decodeNumber(tokenName, numberName))
|
if (!decodeNumber(tokenName, numberName))
|
||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
name = String(numberName.asCString());
|
name = numberName.asString();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -565,7 +568,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
return decodeDouble(token, decoded);
|
||||||
auto digit(static_cast<Value::UInt>(c - '0'));
|
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||||
if (value >= threshold) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, b) this is the last digit, and
|
// a) we've only just touched the limit, b) this is the last digit, and
|
||||||
@@ -629,7 +632,7 @@ bool Reader::decodeString(Token& token, String& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
break;
|
break;
|
||||||
else if (c == '\\') {
|
if (c == '\\') {
|
||||||
if (current == end)
|
if (current == end)
|
||||||
return addError("Empty escape sequence in string", token, current);
|
return addError("Empty escape sequence in string", token, current);
|
||||||
Char escape = *current++;
|
Char escape = *current++;
|
||||||
@@ -798,7 +801,9 @@ String Reader::getFormatedErrorMessages() const {
|
|||||||
|
|
||||||
String Reader::getFormattedErrorMessages() const {
|
String Reader::getFormattedErrorMessages() const {
|
||||||
String formattedMessage;
|
String formattedMessage;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
formattedMessage +=
|
formattedMessage +=
|
||||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||||
formattedMessage += " " + error.message_ + "\n";
|
formattedMessage += " " + error.message_ + "\n";
|
||||||
@@ -811,7 +816,9 @@ String Reader::getFormattedErrorMessages() const {
|
|||||||
|
|
||||||
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
||||||
std::vector<Reader::StructuredError> allErrors;
|
std::vector<Reader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
Reader::StructuredError structured;
|
Reader::StructuredError structured;
|
||||||
structured.offset_start = error.token_.start_ - begin_;
|
structured.offset_start = error.token_.start_ - begin_;
|
||||||
structured.offset_limit = error.token_.end_ - begin_;
|
structured.offset_limit = error.token_.end_ - begin_;
|
||||||
@@ -832,7 +839,7 @@ bool Reader::pushError(const Value& value, const String& message) {
|
|||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.token_ = token;
|
info.token_ = token;
|
||||||
info.message_ = message;
|
info.message_ = message;
|
||||||
info.extra_ = nullptr;
|
info.extra_ = JSONCPP_NULL;
|
||||||
errors_.push_back(info);
|
errors_.push_back(info);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -863,6 +870,7 @@ class OurFeatures {
|
|||||||
public:
|
public:
|
||||||
static OurFeatures all();
|
static OurFeatures all();
|
||||||
bool allowComments_;
|
bool allowComments_;
|
||||||
|
bool allowTrailingCommas_;
|
||||||
bool strictRoot_;
|
bool strictRoot_;
|
||||||
bool allowDroppedNullPlaceholders_;
|
bool allowDroppedNullPlaceholders_;
|
||||||
bool allowNumericKeys_;
|
bool allowNumericKeys_;
|
||||||
@@ -870,10 +878,11 @@ public:
|
|||||||
bool failIfExtra_;
|
bool failIfExtra_;
|
||||||
bool rejectDupKeys_;
|
bool rejectDupKeys_;
|
||||||
bool allowSpecialFloats_;
|
bool allowSpecialFloats_;
|
||||||
|
bool skipBom_;
|
||||||
size_t stackLimit_;
|
size_t stackLimit_;
|
||||||
}; // OurFeatures
|
}; // OurFeatures
|
||||||
|
|
||||||
OurFeatures OurFeatures::all() { return {}; }
|
OurFeatures OurFeatures::all() { return OurFeatures(); }
|
||||||
|
|
||||||
// Implementation of class Reader
|
// Implementation of class Reader
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
@@ -882,15 +891,15 @@ OurFeatures OurFeatures::all() { return {}; }
|
|||||||
// for implementing JSON reading.
|
// for implementing JSON reading.
|
||||||
class OurReader {
|
class OurReader {
|
||||||
public:
|
public:
|
||||||
using Char = char;
|
typedef char Char;
|
||||||
using Location = const Char*;
|
typedef const Char* Location;
|
||||||
struct StructuredError {
|
struct StructuredError {
|
||||||
ptrdiff_t offset_start;
|
ptrdiff_t offset_start;
|
||||||
ptrdiff_t offset_limit;
|
ptrdiff_t offset_limit;
|
||||||
String message;
|
String message;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit OurReader(OurFeatures const& features);
|
JSONCPP_OP_EXPLICIT OurReader(OurFeatures const& features);
|
||||||
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
bool collectComments = true);
|
bool collectComments = true);
|
||||||
String getFormattedErrorMessages() const;
|
String getFormattedErrorMessages() const;
|
||||||
@@ -934,10 +943,11 @@ private:
|
|||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
using Errors = std::deque<ErrorInfo>;
|
typedef std::deque<ErrorInfo> Errors;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
|
void skipBom(bool skipBom);
|
||||||
bool match(const Char* pattern, int patternLength);
|
bool match(const Char* pattern, int patternLength);
|
||||||
bool readComment();
|
bool readComment();
|
||||||
bool readCStyleComment(bool* containsNewLineResult);
|
bool readCStyleComment(bool* containsNewLineResult);
|
||||||
@@ -958,7 +968,8 @@ private:
|
|||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||||
Location end, unsigned int& unicode);
|
Location end, unsigned int& unicode);
|
||||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
bool addError(const String& message, Token& token,
|
||||||
|
Location extra = JSONCPP_NULL);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const String& message, Token& token,
|
bool addErrorAndRecover(const String& message, Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
@@ -974,21 +985,21 @@ private:
|
|||||||
static String normalizeEOL(Location begin, Location end);
|
static String normalizeEOL(Location begin, Location end);
|
||||||
static bool containsNewLine(Location begin, Location end);
|
static bool containsNewLine(Location begin, Location end);
|
||||||
|
|
||||||
using Nodes = std::stack<Value*>;
|
typedef std::stack<Value*> Nodes;
|
||||||
|
|
||||||
Nodes nodes_{};
|
Nodes nodes_;
|
||||||
Errors errors_{};
|
Errors errors_;
|
||||||
String document_{};
|
String document_;
|
||||||
Location begin_ = nullptr;
|
Location begin_;
|
||||||
Location end_ = nullptr;
|
Location end_;
|
||||||
Location current_ = nullptr;
|
Location current_;
|
||||||
Location lastValueEnd_ = nullptr;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_ = nullptr;
|
Value* lastValue_;
|
||||||
bool lastValueHasAComment_ = false;
|
bool lastValueHasAComment_;
|
||||||
String commentsBefore_{};
|
String commentsBefore_;
|
||||||
|
|
||||||
OurFeatures const features_;
|
OurFeatures const features_;
|
||||||
bool collectComments_ = false;
|
bool collectComments_;
|
||||||
}; // OurReader
|
}; // OurReader
|
||||||
|
|
||||||
// complete copy of Read impl, for OurReader
|
// complete copy of Read impl, for OurReader
|
||||||
@@ -1001,7 +1012,11 @@ bool OurReader::containsNewLine(OurReader::Location begin,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
|
OurReader::OurReader(OurFeatures const& features)
|
||||||
|
: errors_(), document_(), begin_(JSONCPP_NULL), end_(JSONCPP_NULL),
|
||||||
|
current_(JSONCPP_NULL), lastValueEnd_(JSONCPP_NULL),
|
||||||
|
lastValue_(JSONCPP_NULL), lastValueHasAComment_(false), commentsBefore_(),
|
||||||
|
features_(features), collectComments_(false) {}
|
||||||
|
|
||||||
bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
bool collectComments) {
|
bool collectComments) {
|
||||||
@@ -1013,14 +1028,16 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
end_ = endDoc;
|
end_ = endDoc;
|
||||||
collectComments_ = collectComments;
|
collectComments_ = collectComments;
|
||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = nullptr;
|
lastValueEnd_ = JSONCPP_NULL;
|
||||||
lastValue_ = nullptr;
|
lastValue_ = JSONCPP_NULL;
|
||||||
commentsBefore_.clear();
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
|
// skip byte order mark if it exists at the beginning of the UTF-8 text.
|
||||||
|
skipBom(features_.skipBom_);
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
Token token;
|
Token token;
|
||||||
@@ -1267,6 +1284,16 @@ void OurReader::skipSpaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OurReader::skipBom(bool skipBom) {
|
||||||
|
// The default behavior is to skip BOM.
|
||||||
|
if (skipBom) {
|
||||||
|
if (strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
|
||||||
|
begin_ += 3;
|
||||||
|
current_ = begin_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool OurReader::match(const Char* pattern, int patternLength) {
|
bool OurReader::match(const Char* pattern, int patternLength) {
|
||||||
if (end_ - current_ < patternLength)
|
if (end_ - current_ < patternLength)
|
||||||
return false;
|
return false;
|
||||||
@@ -1337,7 +1364,7 @@ void OurReader::addComment(Location begin, Location end,
|
|||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const String& normalized = normalizeEOL(begin, end);
|
const String& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != nullptr);
|
assert(lastValue_ != JSONCPP_NULL);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
} else {
|
} else {
|
||||||
commentsBefore_ += normalized;
|
commentsBefore_ += normalized;
|
||||||
@@ -1349,11 +1376,10 @@ bool OurReader::readCStyleComment(bool* containsNewLineResult) {
|
|||||||
|
|
||||||
while ((current_ + 1) < end_) {
|
while ((current_ + 1) < end_) {
|
||||||
Char c = getNextChar();
|
Char c = getNextChar();
|
||||||
if (c == '*' && *current_ == '/') {
|
if (c == '*' && *current_ == '/')
|
||||||
break;
|
break;
|
||||||
} else if (c == '\n') {
|
if (c == '\n')
|
||||||
*containsNewLineResult = true;
|
*containsNewLineResult = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getNextChar() == '/';
|
return getNextChar() == '/';
|
||||||
@@ -1437,7 +1463,9 @@ bool OurReader::readObject(Token& token) {
|
|||||||
initialTokenOk = readToken(tokenName);
|
initialTokenOk = readToken(tokenName);
|
||||||
if (!initialTokenOk)
|
if (!initialTokenOk)
|
||||||
break;
|
break;
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
if (tokenName.type_ == tokenObjectEnd &&
|
||||||
|
(name.empty() ||
|
||||||
|
features_.allowTrailingCommas_)) // empty object or trailing comma
|
||||||
return true;
|
return true;
|
||||||
name.clear();
|
name.clear();
|
||||||
if (tokenName.type_ == tokenString) {
|
if (tokenName.type_ == tokenString) {
|
||||||
@@ -1491,15 +1519,19 @@ bool OurReader::readArray(Token& token) {
|
|||||||
Value init(arrayValue);
|
Value init(arrayValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
skipSpaces();
|
|
||||||
if (current_ != end_ && *current_ == ']') // empty array
|
|
||||||
{
|
|
||||||
Token endArray;
|
|
||||||
readToken(endArray);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (;;) {
|
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++];
|
Value& value = currentValue()[index++];
|
||||||
nodes_.push(&value);
|
nodes_.push(&value);
|
||||||
bool ok = readValue();
|
bool ok = readValue();
|
||||||
@@ -1548,32 +1580,36 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
// We assume we can represent the largest and smallest integer types as
|
// We assume we can represent the largest and smallest integer types as
|
||||||
// unsigned integers with separate sign. This is only true if they can fit
|
// unsigned integers with separate sign. This is only true if they can fit
|
||||||
// into an unsigned integer.
|
// into an unsigned integer.
|
||||||
static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
|
JSONCPP_STATIC_ASSERT(LargestUInt(Value::maxLargestInt) <=
|
||||||
"Int must be smaller than UInt");
|
Value::maxLargestUInt,
|
||||||
|
"Int must be smaller than Uint");
|
||||||
// We need to convert minLargestInt into a positive number. The easiest way
|
// We need to convert minLargestInt into a positive number. The easiest way
|
||||||
// to do this conversion is to assume our "threshold" value of minLargestInt
|
// to do this conversion is to assume our "threshold" value of minLargestInt
|
||||||
// divided by 10 can fit in maxLargestInt when absolute valued. This should
|
// divided by 10 can fit in maxLargestInt when absolute valued. This should
|
||||||
// be a safe assumption.
|
// be a safe assumption.
|
||||||
static_assert(Value::minLargestInt <= -Value::maxLargestInt,
|
JSONCPP_STATIC_ASSERT(
|
||||||
"The absolute value of minLargestInt must be greater than or "
|
Value::minLargestInt <= -Value::maxLargestInt,
|
||||||
"equal to maxLargestInt");
|
"The absolute value of minLargestInt must ve greater than or"
|
||||||
static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
|
"equal to maxLargestInt");
|
||||||
"The absolute value of minLargestInt must be only 1 magnitude "
|
|
||||||
"larger than maxLargest Int");
|
|
||||||
|
|
||||||
static constexpr Value::LargestUInt positive_threshold =
|
JSONCPP_STATIC_ASSERT(
|
||||||
|
Value::minLargestInt / 10 >= -Value::maxLargestInt,
|
||||||
|
"The absolute value of minLargestInt must be only 1 magnitude"
|
||||||
|
"larger than maxLargestInt");
|
||||||
|
|
||||||
|
static JSONCPP_CONST Value::LargestUInt positive_threshold =
|
||||||
Value::maxLargestUInt / 10;
|
Value::maxLargestUInt / 10;
|
||||||
static constexpr Value::UInt positive_last_digit = Value::maxLargestUInt % 10;
|
static JSONCPP_CONST Value::UInt positive_last_digit =
|
||||||
|
Value::maxLargestUInt % 10;
|
||||||
|
|
||||||
// For the negative values, we have to be more careful. Since typically
|
// For the negative values, we have to be more careful. Since typically
|
||||||
// -Value::minLargestInt will cause an overflow, we first divide by 10 and
|
// -Value::minLargestInt will cause an overflow, we first divide by 10 and
|
||||||
// then take the inverse. This assumes that minLargestInt is only a single
|
// 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
|
// power of 10 different in magnitude, which we check above. For the last
|
||||||
// digit, we take the modulus before negating for the same reason.
|
// digit, we take the modulus before negating for the same reason.
|
||||||
static constexpr Value::LargestUInt negative_threshold =
|
static JSONCPP_CONST Value::LargestUInt negative_threshold =
|
||||||
Value::LargestUInt(-(Value::minLargestInt / 10));
|
Value::LargestUInt(-(Value::minLargestInt / 10));
|
||||||
static constexpr Value::UInt negative_last_digit =
|
static JSONCPP_CONST Value::UInt negative_last_digit =
|
||||||
Value::UInt(-(Value::minLargestInt % 10));
|
Value::UInt(-(Value::minLargestInt % 10));
|
||||||
|
|
||||||
const Value::LargestUInt threshold =
|
const Value::LargestUInt threshold =
|
||||||
@@ -1654,9 +1690,9 @@ bool OurReader::decodeString(Token& token, String& decoded) {
|
|||||||
Location end = token.end_ - 1; // do not include '"'
|
Location end = token.end_ - 1; // do not include '"'
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '"') {
|
if (c == '"')
|
||||||
break;
|
break;
|
||||||
} else if (c == '\\') {
|
if (c == '\\') {
|
||||||
if (current == end)
|
if (current == end)
|
||||||
return addError("Empty escape sequence in string", token, current);
|
return addError("Empty escape sequence in string", token, current);
|
||||||
Char escape = *current++;
|
Char escape = *current++;
|
||||||
@@ -1820,7 +1856,9 @@ String OurReader::getLocationLineAndColumn(Location location) const {
|
|||||||
|
|
||||||
String OurReader::getFormattedErrorMessages() const {
|
String OurReader::getFormattedErrorMessages() const {
|
||||||
String formattedMessage;
|
String formattedMessage;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
formattedMessage +=
|
formattedMessage +=
|
||||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||||
formattedMessage += " " + error.message_ + "\n";
|
formattedMessage += " " + error.message_ + "\n";
|
||||||
@@ -1833,7 +1871,9 @@ String OurReader::getFormattedErrorMessages() const {
|
|||||||
|
|
||||||
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
||||||
std::vector<OurReader::StructuredError> allErrors;
|
std::vector<OurReader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
|
itError != errors_.end(); ++itError) {
|
||||||
|
const ErrorInfo& error = *itError;
|
||||||
OurReader::StructuredError structured;
|
OurReader::StructuredError structured;
|
||||||
structured.offset_start = error.token_.start_ - begin_;
|
structured.offset_start = error.token_.start_ - begin_;
|
||||||
structured.offset_limit = error.token_.end_ - begin_;
|
structured.offset_limit = error.token_.end_ - begin_;
|
||||||
@@ -1851,7 +1891,7 @@ public:
|
|||||||
OurCharReader(bool collectComments, OurFeatures const& features)
|
OurCharReader(bool collectComments, OurFeatures const& features)
|
||||||
: collectComments_(collectComments), reader_(features) {}
|
: collectComments_(collectComments), reader_(features) {}
|
||||||
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
String* errs) override {
|
String* errs) JSONCPP_OVERRIDE {
|
||||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||||
if (errs) {
|
if (errs) {
|
||||||
*errs = reader_.getFormattedErrorMessages();
|
*errs = reader_.getFormattedErrorMessages();
|
||||||
@@ -1861,11 +1901,12 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
||||||
CharReaderBuilder::~CharReaderBuilder() = default;
|
CharReaderBuilder::~CharReaderBuilder() {}
|
||||||
CharReader* CharReaderBuilder::newCharReader() const {
|
CharReader* CharReaderBuilder::newCharReader() const {
|
||||||
bool collectComments = settings_["collectComments"].asBool();
|
bool collectComments = settings_["collectComments"].asBool();
|
||||||
OurFeatures features = OurFeatures::all();
|
OurFeatures features = OurFeatures::all();
|
||||||
features.allowComments_ = settings_["allowComments"].asBool();
|
features.allowComments_ = settings_["allowComments"].asBool();
|
||||||
|
features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
|
||||||
features.strictRoot_ = settings_["strictRoot"].asBool();
|
features.strictRoot_ = settings_["strictRoot"].asBool();
|
||||||
features.allowDroppedNullPlaceholders_ =
|
features.allowDroppedNullPlaceholders_ =
|
||||||
settings_["allowDroppedNullPlaceholders"].asBool();
|
settings_["allowDroppedNullPlaceholders"].asBool();
|
||||||
@@ -1878,12 +1919,14 @@ CharReader* CharReaderBuilder::newCharReader() const {
|
|||||||
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
||||||
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
|
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
|
||||||
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
|
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
|
||||||
|
features.skipBom_ = settings_["skipBom"].asBool();
|
||||||
return new OurCharReader(collectComments, features);
|
return new OurCharReader(collectComments, features);
|
||||||
}
|
}
|
||||||
static void getValidReaderKeys(std::set<String>* valid_keys) {
|
static void getValidReaderKeys(std::set<String>* valid_keys) {
|
||||||
valid_keys->clear();
|
valid_keys->clear();
|
||||||
valid_keys->insert("collectComments");
|
valid_keys->insert("collectComments");
|
||||||
valid_keys->insert("allowComments");
|
valid_keys->insert("allowComments");
|
||||||
|
valid_keys->insert("allowTrailingCommas");
|
||||||
valid_keys->insert("strictRoot");
|
valid_keys->insert("strictRoot");
|
||||||
valid_keys->insert("allowDroppedNullPlaceholders");
|
valid_keys->insert("allowDroppedNullPlaceholders");
|
||||||
valid_keys->insert("allowNumericKeys");
|
valid_keys->insert("allowNumericKeys");
|
||||||
@@ -1892,6 +1935,7 @@ static void getValidReaderKeys(std::set<String>* valid_keys) {
|
|||||||
valid_keys->insert("failIfExtra");
|
valid_keys->insert("failIfExtra");
|
||||||
valid_keys->insert("rejectDupKeys");
|
valid_keys->insert("rejectDupKeys");
|
||||||
valid_keys->insert("allowSpecialFloats");
|
valid_keys->insert("allowSpecialFloats");
|
||||||
|
valid_keys->insert("skipBom");
|
||||||
}
|
}
|
||||||
bool CharReaderBuilder::validate(Json::Value* invalid) const {
|
bool CharReaderBuilder::validate(Json::Value* invalid) const {
|
||||||
Json::Value my_invalid;
|
Json::Value my_invalid;
|
||||||
@@ -1917,6 +1961,7 @@ Value& CharReaderBuilder::operator[](const String& key) {
|
|||||||
void CharReaderBuilder::strictMode(Json::Value* settings) {
|
void CharReaderBuilder::strictMode(Json::Value* settings) {
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
(*settings)["allowComments"] = false;
|
(*settings)["allowComments"] = false;
|
||||||
|
(*settings)["allowTrailingCommas"] = false;
|
||||||
(*settings)["strictRoot"] = true;
|
(*settings)["strictRoot"] = true;
|
||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
@@ -1925,6 +1970,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
|
|||||||
(*settings)["failIfExtra"] = true;
|
(*settings)["failIfExtra"] = true;
|
||||||
(*settings)["rejectDupKeys"] = true;
|
(*settings)["rejectDupKeys"] = true;
|
||||||
(*settings)["allowSpecialFloats"] = false;
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = true;
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
}
|
}
|
||||||
// static
|
// static
|
||||||
@@ -1932,6 +1978,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
|
|||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
(*settings)["collectComments"] = true;
|
(*settings)["collectComments"] = true;
|
||||||
(*settings)["allowComments"] = true;
|
(*settings)["allowComments"] = true;
|
||||||
|
(*settings)["allowTrailingCommas"] = true;
|
||||||
(*settings)["strictRoot"] = false;
|
(*settings)["strictRoot"] = false;
|
||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
@@ -1940,6 +1987,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
|
|||||||
(*settings)["failIfExtra"] = false;
|
(*settings)["failIfExtra"] = false;
|
||||||
(*settings)["rejectDupKeys"] = false;
|
(*settings)["rejectDupKeys"] = false;
|
||||||
(*settings)["allowSpecialFloats"] = false;
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = true;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1955,7 +2003,9 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
|
|||||||
char const* end = begin + doc.size();
|
char const* end = begin + doc.size();
|
||||||
// Note that we do not actually need a null-terminator.
|
// Note that we do not actually need a null-terminator.
|
||||||
CharReaderPtr const reader(fact.newCharReader());
|
CharReaderPtr const reader(fact.newCharReader());
|
||||||
return reader->parse(begin, end, root, errs);
|
bool ret = reader->parse(begin, end, root, errs);
|
||||||
|
delete reader;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
IStream& operator>>(IStream& sin, Value& root) {
|
IStream& operator>>(IStream& sin, Value& root) {
|
||||||
|
@@ -8,16 +8,14 @@
|
|||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
#include <json/writer.h>
|
#include <json/writer.h>
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#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
|
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
@@ -50,14 +48,6 @@ int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
#define JSON_ASSERT_UNREACHABLE assert(false)
|
#define JSON_ASSERT_UNREACHABLE assert(false)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
template <typename T>
|
|
||||||
static std::unique_ptr<T> cloneUnique(const std::unique_ptr<T>& p) {
|
|
||||||
std::unique_ptr<T> r;
|
|
||||||
if (p) {
|
|
||||||
r = std::unique_ptr<T>(new T(*p));
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a walkaround to avoid the static initialization of Value::null.
|
// This is a walkaround to avoid the static initialization of Value::null.
|
||||||
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
|
// kNull must be word-aligned to avoid crashing on ARM. We use an alignment of
|
||||||
@@ -121,7 +111,7 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
|
|||||||
length = Value::maxInt - 1;
|
length = Value::maxInt - 1;
|
||||||
|
|
||||||
char* newString = static_cast<char*>(malloc(length + 1));
|
char* newString = static_cast<char*>(malloc(length + 1));
|
||||||
if (newString == nullptr) {
|
if (newString == JSONCPP_NULL) {
|
||||||
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
}
|
}
|
||||||
@@ -140,9 +130,9 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
|
|||||||
sizeof(unsigned) - 1U,
|
sizeof(unsigned) - 1U,
|
||||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"length too big for prefixing");
|
"length too big for prefixing");
|
||||||
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
|
size_t actualLength = sizeof(length) + length + 1;
|
||||||
char* newString = static_cast<char*>(malloc(actualLength));
|
char* newString = static_cast<char*>(malloc(actualLength));
|
||||||
if (newString == nullptr) {
|
if (newString == JSONCPP_NULL) {
|
||||||
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
}
|
}
|
||||||
@@ -202,8 +192,8 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
|||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
Exception::Exception(String msg) : msg_(std::move(msg)) {}
|
Exception::Exception(String msg) : msg_(JSONCPP_MOVE(msg)) {}
|
||||||
Exception::~Exception() JSONCPP_NOEXCEPT = default;
|
Exception::~Exception() JSONCPP_NOEXCEPT {}
|
||||||
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
|
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
|
||||||
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
||||||
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
||||||
@@ -214,8 +204,14 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
|||||||
throw LogicError(msg);
|
throw LogicError(msg);
|
||||||
}
|
}
|
||||||
#else // !JSON_USE_EXCEPTION
|
#else // !JSON_USE_EXCEPTION
|
||||||
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { abort(); }
|
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
||||||
JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
|
std::cerr << msg << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
||||||
|
std::cerr << msg << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -229,7 +225,8 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
|
|||||||
// Notes: policy_ indicates if the string was allocated when
|
// Notes: policy_ indicates if the string was allocated when
|
||||||
// a string is stored.
|
// a string is stored.
|
||||||
|
|
||||||
Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
|
Value::CZString::CZString(ArrayIndex index)
|
||||||
|
: cstr_(JSONCPP_NULL), index_(index) {}
|
||||||
|
|
||||||
Value::CZString::CZString(char const* str, unsigned length,
|
Value::CZString::CZString(char const* str, unsigned length,
|
||||||
DuplicationPolicy allocate)
|
DuplicationPolicy allocate)
|
||||||
@@ -240,9 +237,10 @@ Value::CZString::CZString(char const* str, unsigned length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
Value::CZString::CZString(const CZString& other) {
|
Value::CZString::CZString(const CZString& other) {
|
||||||
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
|
cstr_ =
|
||||||
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
(other.storage_.policy_ != noDuplication && other.cstr_ != JSONCPP_NULL
|
||||||
: other.cstr_);
|
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
||||||
|
: other.cstr_);
|
||||||
storage_.policy_ =
|
storage_.policy_ =
|
||||||
static_cast<unsigned>(
|
static_cast<unsigned>(
|
||||||
other.cstr_
|
other.cstr_
|
||||||
@@ -254,12 +252,12 @@ Value::CZString::CZString(const CZString& other) {
|
|||||||
3U;
|
3U;
|
||||||
storage_.length_ = other.storage_.length_;
|
storage_.length_ = other.storage_.length_;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::CZString::CZString(CZString&& other)
|
Value::CZString::CZString(CZString&& other)
|
||||||
: cstr_(other.cstr_), index_(other.index_) {
|
: cstr_(other.cstr_), index_(other.index_) {
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
Value::CZString::~CZString() {
|
Value::CZString::~CZString() {
|
||||||
if (cstr_ && storage_.policy_ == duplicate) {
|
if (cstr_ && storage_.policy_ == duplicate) {
|
||||||
releaseStringValue(const_cast<char*>(cstr_),
|
releaseStringValue(const_cast<char*>(cstr_),
|
||||||
@@ -280,14 +278,14 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
|
|||||||
index_ = other.index_;
|
index_ = other.index_;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
||||||
cstr_ = other.cstr_;
|
cstr_ = other.cstr_;
|
||||||
index_ = other.index_;
|
index_ = other.index_;
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = JSONCPP_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
bool Value::CZString::operator<(const CZString& other) const {
|
bool Value::CZString::operator<(const CZString& other) const {
|
||||||
if (!cstr_)
|
if (!cstr_)
|
||||||
return index_ < other.index_;
|
return index_ < other.index_;
|
||||||
@@ -396,7 +394,7 @@ Value::Value(double value) {
|
|||||||
|
|
||||||
Value::Value(const char* value) {
|
Value::Value(const char* value) {
|
||||||
initBasic(stringValue, true);
|
initBasic(stringValue, true);
|
||||||
JSON_ASSERT_MESSAGE(value != nullptr,
|
JSON_ASSERT_MESSAGE(value != JSONCPP_NULL,
|
||||||
"Null Value Passed to Value Constructor");
|
"Null Value Passed to Value Constructor");
|
||||||
value_.string_ = duplicateAndPrefixStringValue(
|
value_.string_ = duplicateAndPrefixStringValue(
|
||||||
value, static_cast<unsigned>(strlen(value)));
|
value, static_cast<unsigned>(strlen(value)));
|
||||||
@@ -419,14 +417,6 @@ Value::Value(const StaticString& value) {
|
|||||||
value_.string_ = const_cast<char*>(value.c_str());
|
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) {
|
Value::Value(bool value) {
|
||||||
initBasic(booleanValue);
|
initBasic(booleanValue);
|
||||||
value_.bool_ = value;
|
value_.bool_ = value;
|
||||||
@@ -436,11 +426,12 @@ Value::Value(const Value& other) {
|
|||||||
dupPayload(other);
|
dupPayload(other);
|
||||||
dupMeta(other);
|
dupMeta(other);
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value::Value(Value&& other) {
|
Value::Value(Value&& other) {
|
||||||
initBasic(nullValue);
|
initBasic(nullValue);
|
||||||
swap(other);
|
swap(other);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::~Value() {
|
Value::~Value() {
|
||||||
releasePayload();
|
releasePayload();
|
||||||
@@ -451,11 +442,12 @@ Value& Value::operator=(const Value& other) {
|
|||||||
Value(other).swap(*this);
|
Value(other).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#if JSONCPP_CXX_STD_11
|
||||||
Value& Value::operator=(Value&& other) {
|
Value& Value::operator=(Value&& other) {
|
||||||
other.swap(*this);
|
other.swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Value::swapPayload(Value& other) {
|
void Value::swapPayload(Value& other) {
|
||||||
std::swap(bits_, other.bits_);
|
std::swap(bits_, other.bits_);
|
||||||
@@ -507,8 +499,9 @@ bool Value::operator<(const Value& other) const {
|
|||||||
case booleanValue:
|
case booleanValue:
|
||||||
return value_.bool_ < other.value_.bool_;
|
return value_.bool_ < other.value_.bool_;
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
if ((value_.string_ == JSONCPP_NULL) ||
|
||||||
return other.value_.string_ != nullptr;
|
(other.value_.string_ == JSONCPP_NULL)) {
|
||||||
|
return other.value_.string_ != JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
unsigned other_len;
|
unsigned other_len;
|
||||||
@@ -529,9 +522,10 @@ bool Value::operator<(const Value& other) const {
|
|||||||
}
|
}
|
||||||
case arrayValue:
|
case arrayValue:
|
||||||
case objectValue: {
|
case objectValue: {
|
||||||
int delta = int(value_.map_->size() - other.value_.map_->size());
|
long unsigned int thisSize = value_.map_->size();
|
||||||
if (delta)
|
long unsigned int otherSize = other.value_.map_->size();
|
||||||
return delta < 0;
|
if (thisSize != otherSize)
|
||||||
|
return thisSize < otherSize;
|
||||||
return (*value_.map_) < (*other.value_.map_);
|
return (*value_.map_) < (*other.value_.map_);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -561,7 +555,8 @@ bool Value::operator==(const Value& other) const {
|
|||||||
case booleanValue:
|
case booleanValue:
|
||||||
return value_.bool_ == other.value_.bool_;
|
return value_.bool_ == other.value_.bool_;
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
if ((value_.string_ == JSONCPP_NULL) ||
|
||||||
|
(other.value_.string_ == JSONCPP_NULL)) {
|
||||||
return (value_.string_ == other.value_.string_);
|
return (value_.string_ == other.value_.string_);
|
||||||
}
|
}
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
@@ -593,8 +588,8 @@ bool Value::operator!=(const Value& other) const { return !(*this == other); }
|
|||||||
const char* Value::asCString() const {
|
const char* Value::asCString() const {
|
||||||
JSON_ASSERT_MESSAGE(type() == stringValue,
|
JSON_ASSERT_MESSAGE(type() == stringValue,
|
||||||
"in Json::Value::asCString(): requires stringValue");
|
"in Json::Value::asCString(): requires stringValue");
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
char const* this_str;
|
char const* this_str;
|
||||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
|
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
|
||||||
@@ -619,7 +614,7 @@ unsigned Value::getCStringLength() const {
|
|||||||
bool Value::getString(char const** begin, char const** end) const {
|
bool Value::getString(char const** begin, char const** end) const {
|
||||||
if (type() != stringValue)
|
if (type() != stringValue)
|
||||||
return false;
|
return false;
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return false;
|
return false;
|
||||||
unsigned length;
|
unsigned length;
|
||||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
||||||
@@ -633,7 +628,7 @@ String Value::asString() const {
|
|||||||
case nullValue:
|
case nullValue:
|
||||||
return "";
|
return "";
|
||||||
case stringValue: {
|
case stringValue: {
|
||||||
if (value_.string_ == nullptr)
|
if (value_.string_ == JSONCPP_NULL)
|
||||||
return "";
|
return "";
|
||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
char const* this_str;
|
char const* this_str;
|
||||||
@@ -654,15 +649,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 {
|
Value::Int Value::asInt() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case intValue:
|
case intValue:
|
||||||
@@ -825,7 +811,7 @@ bool Value::asBool() const {
|
|||||||
return value_.uint_ != 0;
|
return value_.uint_ != 0;
|
||||||
case realValue: {
|
case realValue: {
|
||||||
// According to JavaScript language zero or NaN is regarded as false
|
// According to JavaScript language zero or NaN is regarded as false
|
||||||
const auto value_classification = std::fpclassify(value_.real_);
|
const int value_classification = std::fpclassify(value_.real_);
|
||||||
return value_classification != FP_ZERO && value_classification != FP_NAN;
|
return value_classification != FP_ZERO && value_classification != FP_NAN;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -894,8 +880,7 @@ ArrayIndex Value::size() const {
|
|||||||
bool Value::empty() const {
|
bool Value::empty() const {
|
||||||
if (isNull() || isArray() || isObject())
|
if (isNull() || isArray() || isObject())
|
||||||
return size() == 0U;
|
return size() == 0U;
|
||||||
else
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::operator bool() const { return !isNull(); }
|
Value::operator bool() const { return !isNull(); }
|
||||||
@@ -941,7 +926,7 @@ Value& Value::operator[](ArrayIndex index) {
|
|||||||
if (type() == nullValue)
|
if (type() == nullValue)
|
||||||
*this = Value(arrayValue);
|
*this = Value(arrayValue);
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
auto it = value_.map_->lower_bound(key);
|
ObjectValues::iterator it = value_.map_->lower_bound(key);
|
||||||
if (it != value_.map_->end() && (*it).first == key)
|
if (it != value_.map_->end() && (*it).first == key)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@@ -980,7 +965,7 @@ const Value& Value::operator[](int index) const {
|
|||||||
void Value::initBasic(ValueType type, bool allocated) {
|
void Value::initBasic(ValueType type, bool allocated) {
|
||||||
setType(type);
|
setType(type);
|
||||||
setIsAllocated(allocated);
|
setIsAllocated(allocated);
|
||||||
comments_ = Comments{};
|
comments_ = Comments();
|
||||||
start_ = 0;
|
start_ = 0;
|
||||||
limit_ = 0;
|
limit_ = 0;
|
||||||
}
|
}
|
||||||
@@ -1055,7 +1040,7 @@ Value& Value::resolveReference(const char* key) {
|
|||||||
*this = Value(objectValue);
|
*this = Value(objectValue);
|
||||||
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
|
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
|
||||||
CZString::noDuplication); // NOTE!
|
CZString::noDuplication); // NOTE!
|
||||||
auto it = value_.map_->lower_bound(actualKey);
|
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@@ -1074,7 +1059,7 @@ Value& Value::resolveReference(char const* key, char const* end) {
|
|||||||
*this = Value(objectValue);
|
*this = Value(objectValue);
|
||||||
CZString actualKey(key, static_cast<unsigned>(end - key),
|
CZString actualKey(key, static_cast<unsigned>(end - key),
|
||||||
CZString::duplicateOnCopy);
|
CZString::duplicateOnCopy);
|
||||||
auto it = value_.map_->lower_bound(actualKey);
|
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
@@ -1096,12 +1081,12 @@ Value const* Value::find(char const* begin, char const* end) const {
|
|||||||
"in Json::Value::find(begin, end): requires "
|
"in Json::Value::find(begin, end): requires "
|
||||||
"objectValue or nullValue");
|
"objectValue or nullValue");
|
||||||
if (type() == nullValue)
|
if (type() == nullValue)
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||||
CZString::noDuplication);
|
CZString::noDuplication);
|
||||||
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
return &(*it).second;
|
return &(*it).second;
|
||||||
}
|
}
|
||||||
Value* Value::demand(char const* begin, char const* end) {
|
Value* Value::demand(char const* begin, char const* end) {
|
||||||
@@ -1135,20 +1120,8 @@ Value& Value::operator[](const StaticString& key) {
|
|||||||
return resolveReference(key.c_str());
|
return resolveReference(key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
#if JSONCPP_CXX_STD_11
|
||||||
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(const Value& value) { return append(Value(value)); }
|
||||||
|
|
||||||
Value& Value::append(Value&& value) {
|
Value& Value::append(Value&& value) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
||||||
"in Json::Value::append: requires arrayValue");
|
"in Json::Value::append: requires arrayValue");
|
||||||
@@ -1157,22 +1130,31 @@ Value& Value::append(Value&& value) {
|
|||||||
}
|
}
|
||||||
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
|
||||||
|
#endif
|
||||||
|
|
||||||
bool Value::insert(ArrayIndex index, Value newValue) {
|
#if JSONCPP_CXX_STD_11
|
||||||
|
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||||
|
return insert(index, Value(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Value::insert(ArrayIndex index, Value&& newValue) {
|
||||||
|
#else
|
||||||
|
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||||
|
#endif
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
||||||
"in Json::Value::insert: requires arrayValue");
|
"in Json::Value::insert: requires arrayValue");
|
||||||
ArrayIndex length = size();
|
ArrayIndex length = size();
|
||||||
if (index > length) {
|
if (index > length) {
|
||||||
return false;
|
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] = JSONCPP_MOVE((*this)[i - 1]);
|
||||||
|
}
|
||||||
|
(*this)[index] = JSONCPP_MOVE(newValue);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::get(char const* begin, char const* end,
|
Value Value::get(char const* begin, char const* end,
|
||||||
Value const& defaultValue) const {
|
Value const& defaultValue) const {
|
||||||
Value const* found = find(begin, end);
|
Value const* found = find(begin, end);
|
||||||
@@ -1191,11 +1173,11 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
|||||||
}
|
}
|
||||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||||
CZString::noDuplication);
|
CZString::noDuplication);
|
||||||
auto it = value_.map_->find(actualKey);
|
ObjectValues::iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return false;
|
return false;
|
||||||
if (removed)
|
if (removed)
|
||||||
*removed = std::move(it->second);
|
*removed = JSONCPP_MOVE(it->second);
|
||||||
value_.map_->erase(it);
|
value_.map_->erase(it);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1221,7 +1203,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
auto it = value_.map_->find(key);
|
ObjectValues::iterator it = value_.map_->find(key);
|
||||||
if (it == value_.map_->end()) {
|
if (it == value_.map_->end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1235,21 +1217,14 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
}
|
}
|
||||||
// erase the last one ("leftover")
|
// erase the last one ("leftover")
|
||||||
CZString keyLast(oldSize - 1);
|
CZString keyLast(oldSize - 1);
|
||||||
auto itLast = value_.map_->find(keyLast);
|
ObjectValues::iterator itLast = value_.map_->find(keyLast);
|
||||||
value_.map_->erase(itLast);
|
value_.map_->erase(itLast);
|
||||||
return true;
|
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 {
|
bool Value::isMember(char const* begin, char const* end) const {
|
||||||
Value const* value = find(begin, end);
|
Value const* value = find(begin, end);
|
||||||
return nullptr != value;
|
return JSONCPP_NULL != value;
|
||||||
}
|
}
|
||||||
bool Value::isMember(char const* key) const {
|
bool Value::isMember(char const* key) const {
|
||||||
return isMember(key, key + strlen(key));
|
return isMember(key, key + strlen(key));
|
||||||
@@ -1258,12 +1233,6 @@ bool Value::isMember(String const& key) const {
|
|||||||
return isMember(key.data(), key.data() + key.length());
|
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 {
|
Value::Members Value::getMemberNames() const {
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
type() == nullValue || type() == objectValue,
|
type() == nullValue || type() == objectValue,
|
||||||
@@ -1279,31 +1248,6 @@ Value::Members Value::getMemberNames() const {
|
|||||||
}
|
}
|
||||||
return members;
|
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) {
|
static bool IsIntegral(double d) {
|
||||||
double integral_part;
|
double integral_part;
|
||||||
@@ -1430,53 +1374,44 @@ bool Value::isArray() const { return type() == arrayValue; }
|
|||||||
|
|
||||||
bool Value::isObject() const { return type() == objectValue; }
|
bool Value::isObject() const { return type() == objectValue; }
|
||||||
|
|
||||||
Value::Comments::Comments(const Comments& that)
|
Value::Comments::Comments(const Comments& that) {
|
||||||
: ptr_{cloneUnique(that.ptr_)} {}
|
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||||
|
ptr_[i] = that.ptr_[i];
|
||||||
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
|
}
|
||||||
|
}
|
||||||
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
||||||
ptr_ = cloneUnique(that.ptr_);
|
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||||
|
ptr_[i] = that.ptr_[i];
|
||||||
|
}
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Comments& Value::Comments::operator=(Comments&& that) {
|
|
||||||
ptr_ = std::move(that.ptr_);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Value::Comments::has(CommentPlacement slot) const {
|
bool Value::Comments::has(CommentPlacement slot) const {
|
||||||
return ptr_ && !(*ptr_)[slot].empty();
|
return !ptr_[slot].empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
String Value::Comments::get(CommentPlacement slot) const {
|
String Value::Comments::get(CommentPlacement slot) const { return ptr_[slot]; }
|
||||||
if (!ptr_)
|
|
||||||
return {};
|
|
||||||
return (*ptr_)[slot];
|
|
||||||
}
|
|
||||||
|
|
||||||
void Value::Comments::set(CommentPlacement slot, String comment) {
|
void Value::Comments::set(CommentPlacement slot, String comment) {
|
||||||
if (!ptr_) {
|
|
||||||
ptr_ = std::unique_ptr<Array>(new Array());
|
|
||||||
}
|
|
||||||
// check comments array boundry.
|
// check comments array boundry.
|
||||||
if (slot < CommentPlacement::numberOfCommentPlacement) {
|
if (slot < numberOfCommentPlacement) {
|
||||||
(*ptr_)[slot] = std::move(comment);
|
ptr_[slot] = comment;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::setComment(String comment, CommentPlacement placement) {
|
void Value::setComment(const char* comment, CommentPlacement placement) {
|
||||||
if (!comment.empty() && (comment.back() == '\n')) {
|
setComment(comment, strlen(comment), placement);
|
||||||
|
}
|
||||||
|
void Value::setComment(const char* comment, size_t len,
|
||||||
|
CommentPlacement placement) {
|
||||||
|
if ((len > 0) && (comment[len - 1] == '\n')) {
|
||||||
// Always discard trailing newline, to aid indentation.
|
// Always discard trailing newline, to aid indentation.
|
||||||
comment.pop_back();
|
len -= 1;
|
||||||
}
|
}
|
||||||
JSON_ASSERT(!comment.empty());
|
comments_.set(placement, String(comment, len));
|
||||||
JSON_ASSERT_MESSAGE(
|
}
|
||||||
comment[0] == '\0' || comment[0] == '/',
|
void Value::setComment(const String& comment, CommentPlacement placement) {
|
||||||
"in Json::Value::setComment(): Comments must start with /");
|
setComment(comment.c_str(), comment.length(), placement);
|
||||||
comments_.set(placement, std::move(comment));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::hasComment(CommentPlacement placement) const {
|
bool Value::hasComment(CommentPlacement placement) const {
|
||||||
return comments_.has(placement);
|
return comments_.has(placement);
|
||||||
}
|
}
|
||||||
@@ -1513,7 +1448,7 @@ Value::const_iterator Value::begin() const {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::const_iterator Value::end() const {
|
Value::const_iterator Value::end() const {
|
||||||
@@ -1526,7 +1461,7 @@ Value::const_iterator Value::end() const {
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return {};
|
return const_iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::iterator Value::begin() {
|
Value::iterator Value::begin() {
|
||||||
@@ -1558,14 +1493,15 @@ Value::iterator Value::end() {
|
|||||||
// class PathArgument
|
// class PathArgument
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PathArgument::PathArgument() = default;
|
PathArgument::PathArgument() {}
|
||||||
|
|
||||||
PathArgument::PathArgument(ArrayIndex index)
|
PathArgument::PathArgument(ArrayIndex index)
|
||||||
: index_(index), kind_(kindIndex) {}
|
: index_(index), kind_(kindIndex) {}
|
||||||
|
|
||||||
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
|
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
|
||||||
|
|
||||||
PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
|
PathArgument::PathArgument(String key)
|
||||||
|
: key_(JSONCPP_MOVE(key)), kind_(kindKey) {}
|
||||||
|
|
||||||
// class Path
|
// class Path
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -1586,7 +1522,7 @@ Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
|
|||||||
void Path::makePath(const String& path, const InArgs& in) {
|
void Path::makePath(const String& path, const InArgs& in) {
|
||||||
const char* current = path.c_str();
|
const char* current = path.c_str();
|
||||||
const char* end = current + path.length();
|
const char* end = current + path.length();
|
||||||
auto itInArg = in.begin();
|
InArgs::const_iterator itInArg = in.begin();
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
if (*current == '[') {
|
if (*current == '[') {
|
||||||
++current;
|
++current;
|
||||||
@@ -1632,7 +1568,9 @@ void Path::invalidPath(const String& /*path*/, int /*location*/) {
|
|||||||
|
|
||||||
const Value& Path::resolve(const Value& root) const {
|
const Value& Path::resolve(const Value& root) const {
|
||||||
const Value* node = &root;
|
const Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
||||||
// Error: unable to resolve path (array value expected at position... )
|
// Error: unable to resolve path (array value expected at position... )
|
||||||
@@ -1657,7 +1595,9 @@ const Value& Path::resolve(const Value& root) const {
|
|||||||
|
|
||||||
Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
||||||
const Value* node = &root;
|
const Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray() || !node->isValidIndex(arg.index_))
|
if (!node->isArray() || !node->isValidIndex(arg.index_))
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
@@ -1675,7 +1615,9 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
|||||||
|
|
||||||
Value& Path::make(Value& root) const {
|
Value& Path::make(Value& root) const {
|
||||||
Value* node = &root;
|
Value* node = &root;
|
||||||
for (const auto& arg : args_) {
|
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||||
|
++itArg) {
|
||||||
|
const PathArgument& arg = *itArg;
|
||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray()) {
|
if (!node->isArray()) {
|
||||||
// Error: node is not an array at position ...
|
// Error: node is not an array at position ...
|
||||||
|
@@ -15,7 +15,7 @@ namespace Json {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase() : current_() {}
|
ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
|
||||||
|
|
||||||
ValueIteratorBase::ValueIteratorBase(
|
ValueIteratorBase::ValueIteratorBase(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
@@ -30,9 +30,6 @@ void ValueIteratorBase::decrement() { --current_; }
|
|||||||
|
|
||||||
ValueIteratorBase::difference_type
|
ValueIteratorBase::difference_type
|
||||||
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
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
|
// Iterator for null value are initialized using the default
|
||||||
// constructor, which initialize current_ to the default
|
// constructor, which initialize current_ to the default
|
||||||
// std::map::iterator. As begin() and end() are two instance
|
// std::map::iterator. As begin() and end() are two instance
|
||||||
@@ -53,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
|
|||||||
++myDistance;
|
++myDistance;
|
||||||
}
|
}
|
||||||
return myDistance;
|
return myDistance;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||||
@@ -102,8 +98,8 @@ char const* ValueIteratorBase::memberName() const {
|
|||||||
char const* ValueIteratorBase::memberName(char const** end) const {
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
const char* cname = (*current_).first.data();
|
const char* cname = (*current_).first.data();
|
||||||
if (!cname) {
|
if (!cname) {
|
||||||
*end = nullptr;
|
*end = JSONCPP_NULL;
|
||||||
return nullptr;
|
return JSONCPP_NULL;
|
||||||
}
|
}
|
||||||
*end = cname + (*current_).first.length();
|
*end = cname + (*current_).first.length();
|
||||||
return cname;
|
return cname;
|
||||||
@@ -117,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueConstIterator::ValueConstIterator() = default;
|
ValueConstIterator::ValueConstIterator() {}
|
||||||
|
|
||||||
ValueConstIterator::ValueConstIterator(
|
ValueConstIterator::ValueConstIterator(
|
||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
@@ -140,7 +136,7 @@ operator=(const ValueIteratorBase& other) {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValueIterator::ValueIterator() = default;
|
ValueIterator::ValueIterator() {}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
@@ -150,7 +146,8 @@ ValueIterator::ValueIterator(const ValueConstIterator& other)
|
|||||||
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueIterator& other) = default;
|
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||||
copy(other);
|
copy(other);
|
||||||
|
@@ -83,11 +83,7 @@
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
typedef StreamWriter* StreamWriterPtr;
|
||||||
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
|
||||||
#else
|
|
||||||
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String valueToString(LargestInt value) {
|
String valueToString(LargestInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
@@ -136,12 +132,12 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
|
|
||||||
String buffer(size_t(36), '\0');
|
String buffer(size_t(36), '\0');
|
||||||
while (true) {
|
while (true) {
|
||||||
int len = jsoncpp_snprintf(
|
int len =
|
||||||
&*buffer.begin(), buffer.size(),
|
jsoncpp_snprintf(&*buffer.begin(), buffer.size(),
|
||||||
(precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
|
(precisionType == significantDigits) ? "%.*g" : "%.*f",
|
||||||
precision, value);
|
precision, value);
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
auto wouldPrint = static_cast<size_t>(len);
|
size_t wouldPrint = static_cast<size_t>(len);
|
||||||
if (wouldPrint >= buffer.size()) {
|
if (wouldPrint >= buffer.size()) {
|
||||||
buffer.resize(wouldPrint + 1);
|
buffer.resize(wouldPrint + 1);
|
||||||
continue;
|
continue;
|
||||||
@@ -153,7 +149,7 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
||||||
|
|
||||||
// strip the zero padding from the right
|
// strip the zero padding from the right
|
||||||
if (precisionType == PrecisionType::decimalPlaces) {
|
if (precisionType == decimalPlaces) {
|
||||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,8 +174,9 @@ static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
|
|||||||
|
|
||||||
char const* const end = s + n;
|
char const* const end = s + n;
|
||||||
for (char const* cur = s; cur < end; ++cur) {
|
for (char const* cur = s; cur < end; ++cur) {
|
||||||
if (*cur == '\\' || *cur == '\"' || *cur < ' ' ||
|
if (*cur == '\\' || *cur == '\"' ||
|
||||||
static_cast<unsigned char>(*cur) < 0x80)
|
static_cast<unsigned char>(*cur) < ' ' ||
|
||||||
|
static_cast<unsigned char>(*cur) >= 0x80)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -266,7 +263,7 @@ static String toHex16Bit(unsigned int x) {
|
|||||||
|
|
||||||
static String valueToQuotedStringN(const char* value, unsigned length,
|
static String valueToQuotedStringN(const char* value, unsigned length,
|
||||||
bool emitUTF8 = false) {
|
bool emitUTF8 = false) {
|
||||||
if (value == nullptr)
|
if (value == JSONCPP_NULL)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (!isAnyCharRequiredQuoting(value, length))
|
if (!isAnyCharRequiredQuoting(value, length))
|
||||||
@@ -350,14 +347,14 @@ String valueToQuotedString(const char* value) {
|
|||||||
|
|
||||||
// Class Writer
|
// Class Writer
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
Writer::~Writer() = default;
|
Writer::~Writer() {}
|
||||||
|
|
||||||
// Class FastWriter
|
// Class FastWriter
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FastWriter::FastWriter()
|
FastWriter::FastWriter()
|
||||||
|
: yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
|
||||||
= default;
|
omitEndingLineFeed_(false) {}
|
||||||
|
|
||||||
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
|
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
|
||||||
|
|
||||||
@@ -413,7 +410,8 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
case objectValue: {
|
case objectValue: {
|
||||||
Value::Members members(value.getMemberNames());
|
Value::Members members(value.getMemberNames());
|
||||||
document_ += '{';
|
document_ += '{';
|
||||||
for (auto it = members.begin(); it != members.end(); ++it) {
|
for (Value::Members::const_iterator it = members.begin();
|
||||||
|
it != members.end(); ++it) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
if (it != members.begin())
|
if (it != members.begin())
|
||||||
document_ += ',';
|
document_ += ',';
|
||||||
@@ -430,7 +428,8 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
// Class StyledWriter
|
// Class StyledWriter
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StyledWriter::StyledWriter() = default;
|
StyledWriter::StyledWriter()
|
||||||
|
: rightMargin_(74), indentSize_(3), addChildValues_() {}
|
||||||
|
|
||||||
String StyledWriter::write(const Value& root) {
|
String StyledWriter::write(const Value& root) {
|
||||||
document_.clear();
|
document_.clear();
|
||||||
@@ -481,7 +480,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
@@ -643,8 +642,9 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StyledStreamWriter::StyledStreamWriter(String indentation)
|
StyledStreamWriter::StyledStreamWriter(String indentation)
|
||||||
: document_(nullptr), indentation_(std::move(indentation)),
|
: document_(JSONCPP_NULL), rightMargin_(74),
|
||||||
addChildValues_(), indented_(false) {}
|
indentation_(JSONCPP_MOVE(indentation)), addChildValues_(),
|
||||||
|
indented_(false) {}
|
||||||
|
|
||||||
void StyledStreamWriter::write(OStream& out, const Value& root) {
|
void StyledStreamWriter::write(OStream& out, const Value& root) {
|
||||||
document_ = &out;
|
document_ = &out;
|
||||||
@@ -658,7 +658,7 @@ void StyledStreamWriter::write(OStream& out, const Value& root) {
|
|||||||
writeValue(root);
|
writeValue(root);
|
||||||
writeCommentAfterValueOnSameLine(root);
|
writeCommentAfterValueOnSameLine(root);
|
||||||
*document_ << "\n";
|
*document_ << "\n";
|
||||||
document_ = nullptr; // Forget the stream, for safety.
|
document_ = JSONCPP_NULL; // Forget the stream, for safety.
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledStreamWriter::writeValue(const Value& value) {
|
void StyledStreamWriter::writeValue(const Value& value) {
|
||||||
@@ -699,7 +699,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
@@ -877,7 +877,7 @@ struct BuiltStyledStreamWriter : public StreamWriter {
|
|||||||
String endingLineFeedSymbol, bool useSpecialFloats,
|
String endingLineFeedSymbol, bool useSpecialFloats,
|
||||||
bool emitUTF8, unsigned int precision,
|
bool emitUTF8, unsigned int precision,
|
||||||
PrecisionType precisionType);
|
PrecisionType precisionType);
|
||||||
int write(Value const& root, OStream* sout) override;
|
int write(Value const& root, OStream* sout) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(Value const& value);
|
void writeValue(Value const& value);
|
||||||
@@ -892,7 +892,7 @@ private:
|
|||||||
void writeCommentAfterValueOnSameLine(Value const& root);
|
void writeCommentAfterValueOnSameLine(Value const& root);
|
||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
|
||||||
using ChildValues = std::vector<String>;
|
typedef std::vector<String> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
String indentString_;
|
String indentString_;
|
||||||
@@ -913,9 +913,10 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
|||||||
String indentation, CommentStyle::Enum cs, String colonSymbol,
|
String indentation, CommentStyle::Enum cs, String colonSymbol,
|
||||||
String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
|
String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
|
||||||
bool emitUTF8, unsigned int precision, PrecisionType precisionType)
|
bool emitUTF8, unsigned int precision, PrecisionType precisionType)
|
||||||
: rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
|
: rightMargin_(74), indentation_(JSONCPP_MOVE(indentation)), cs_(cs),
|
||||||
colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
|
colonSymbol_(JSONCPP_MOVE(colonSymbol)),
|
||||||
endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
|
nullSymbol_(JSONCPP_MOVE(nullSymbol)),
|
||||||
|
endingLineFeedSymbol_(JSONCPP_MOVE(endingLineFeedSymbol)),
|
||||||
addChildValues_(false), indented_(false),
|
addChildValues_(false), indented_(false),
|
||||||
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
|
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
|
||||||
precision_(precision), precisionType_(precisionType) {}
|
precision_(precision), precisionType_(precisionType) {}
|
||||||
@@ -931,7 +932,7 @@ int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
|
|||||||
writeValue(root);
|
writeValue(root);
|
||||||
writeCommentAfterValueOnSameLine(root);
|
writeCommentAfterValueOnSameLine(root);
|
||||||
*sout_ << endingLineFeedSymbol_;
|
*sout_ << endingLineFeedSymbol_;
|
||||||
sout_ = nullptr;
|
sout_ = JSONCPP_NULL;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||||
@@ -974,7 +975,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
else {
|
else {
|
||||||
writeWithIndent("{");
|
writeWithIndent("{");
|
||||||
indent();
|
indent();
|
||||||
auto it = members.begin();
|
Value::Members::const_iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
String const& name = *it;
|
String const& name = *it;
|
||||||
Value const& childValue = value[name];
|
Value const& childValue = value[name];
|
||||||
@@ -1150,11 +1151,11 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
|
|||||||
///////////////
|
///////////////
|
||||||
// StreamWriter
|
// StreamWriter
|
||||||
|
|
||||||
StreamWriter::StreamWriter() : sout_(nullptr) {}
|
StreamWriter::StreamWriter() : sout_(JSONCPP_NULL) {}
|
||||||
StreamWriter::~StreamWriter() = default;
|
StreamWriter::~StreamWriter() {}
|
||||||
StreamWriter::Factory::~Factory() = default;
|
StreamWriter::Factory::~Factory() {}
|
||||||
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
|
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
|
||||||
StreamWriterBuilder::~StreamWriterBuilder() = default;
|
StreamWriterBuilder::~StreamWriterBuilder() {}
|
||||||
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
||||||
const String indentation = settings_["indentation"].asString();
|
const String indentation = settings_["indentation"].asString();
|
||||||
const String cs_str = settings_["commentStyle"].asString();
|
const String cs_str = settings_["commentStyle"].asString();
|
||||||
@@ -1174,9 +1175,9 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
|||||||
}
|
}
|
||||||
PrecisionType precisionType(significantDigits);
|
PrecisionType precisionType(significantDigits);
|
||||||
if (pt_str == "significant") {
|
if (pt_str == "significant") {
|
||||||
precisionType = PrecisionType::significantDigits;
|
precisionType = significantDigits;
|
||||||
} else if (pt_str == "decimal") {
|
} else if (pt_str == "decimal") {
|
||||||
precisionType = PrecisionType::decimalPlaces;
|
precisionType = decimalPlaces;
|
||||||
} else {
|
} else {
|
||||||
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
|
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
|
||||||
}
|
}
|
||||||
@@ -1246,6 +1247,7 @@ String writeString(StreamWriter::Factory const& factory, Value const& root) {
|
|||||||
OStringStream sout;
|
OStringStream sout;
|
||||||
StreamWriterPtr const writer(factory.newStreamWriter());
|
StreamWriterPtr const writer(factory.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
|
delete writer;
|
||||||
return sout.str();
|
return sout.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1253,6 +1255,7 @@ OStream& operator<<(OStream& sout, Value const& root) {
|
|||||||
StreamWriterBuilder builder;
|
StreamWriterBuilder builder;
|
||||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
|
delete writer;
|
||||||
return sout;
|
return sout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,46 +1,37 @@
|
|||||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
|
||||||
add_executable( jsoncpp_test
|
add_executable(jsoncpp_test
|
||||||
jsontest.cpp
|
jsontest.cpp
|
||||||
jsontest.h
|
jsontest.h
|
||||||
fuzz.cpp
|
fuzz.cpp
|
||||||
fuzz.h
|
fuzz.h
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions( JSON_DLL )
|
add_compile_definitions( JSON_DLL )
|
||||||
else()
|
else()
|
||||||
add_definitions( -DJSON_DLL )
|
add_definitions( -DJSON_DLL )
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
||||||
|
|
||||||
# another way to solve issue #90
|
# another way to solve issue #90
|
||||||
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
|
#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
|
# Run unit tests in post-build
|
||||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||||
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
||||||
if(BUILD_SHARED_LIBS)
|
add_custom_command(TARGET jsoncpp_test
|
||||||
# First, copy the shared lib, for Microsoft.
|
POST_BUILD
|
||||||
# Then, run the test executable.
|
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
||||||
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>
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
|
||||||
|
@@ -5,11 +5,9 @@
|
|||||||
|
|
||||||
#include "fuzz.h"
|
#include "fuzz.h"
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <json/config.h>
|
#include <json/config.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
@@ -40,15 +38,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
|
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
|
||||||
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
|
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
|
||||||
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
||||||
|
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
||||||
|
|
||||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
Json::CharReader* reader(builder.newCharReader());
|
||||||
|
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
const char* data_str = reinterpret_cast<const char*>(data);
|
const char* data_str = reinterpret_cast<const char*>(data);
|
||||||
try {
|
try {
|
||||||
reader->parse(data_str, data_str + size, &root, nullptr);
|
reader->parse(data_str, data_str + size, &root, JSONCPP_NULL);
|
||||||
} catch (Json::Exception const&) {
|
} catch (Json::Exception const&) {
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
// Whether it succeeded or not doesn't matter.
|
// Whether it succeeded or not doesn't matter.
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -73,10 +73,11 @@ namespace JsonTest {
|
|||||||
// class TestResult
|
// class TestResult
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestResult::TestResult() {
|
TestResult::TestResult()
|
||||||
|
: predicateId_(1), lastUsedPredicateId_(0), messageTarget_(JSONCPP_NULL) {
|
||||||
// The root predicate has id 0
|
// The root predicate has id 0
|
||||||
rootPredicateNode_.id_ = 0;
|
rootPredicateNode_.id_ = 0;
|
||||||
rootPredicateNode_.next_ = nullptr;
|
rootPredicateNode_.next_ = JSONCPP_NULL;
|
||||||
predicateStackTail_ = &rootPredicateNode_;
|
predicateStackTail_ = &rootPredicateNode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ TestResult& TestResult::addFailure(const char* file, unsigned int line,
|
|||||||
/// added.
|
/// added.
|
||||||
unsigned int nestingLevel = 0;
|
unsigned int nestingLevel = 0;
|
||||||
PredicateContext* lastNode = rootPredicateNode_.next_;
|
PredicateContext* lastNode = rootPredicateNode_.next_;
|
||||||
for (; lastNode != nullptr; lastNode = lastNode->next_) {
|
for (; lastNode != JSONCPP_NULL; lastNode = lastNode->next_) {
|
||||||
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
||||||
{
|
{
|
||||||
lastUsedPredicateId_ = lastNode->id_;
|
lastUsedPredicateId_ = lastNode->id_;
|
||||||
@@ -121,17 +122,18 @@ void TestResult::addFailureInfo(const char* file, unsigned int line,
|
|||||||
|
|
||||||
TestResult& TestResult::popPredicateContext() {
|
TestResult& TestResult::popPredicateContext() {
|
||||||
PredicateContext* lastNode = &rootPredicateNode_;
|
PredicateContext* lastNode = &rootPredicateNode_;
|
||||||
while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
|
while (lastNode->next_ != JSONCPP_NULL &&
|
||||||
|
lastNode->next_->next_ != JSONCPP_NULL) {
|
||||||
lastNode = lastNode->next_;
|
lastNode = lastNode->next_;
|
||||||
}
|
}
|
||||||
// Set message target to popped failure
|
// Set message target to popped failure
|
||||||
PredicateContext* tail = lastNode->next_;
|
PredicateContext* tail = lastNode->next_;
|
||||||
if (tail != nullptr && tail->failure_ != nullptr) {
|
if (tail != JSONCPP_NULL && tail->failure_ != JSONCPP_NULL) {
|
||||||
messageTarget_ = tail->failure_;
|
messageTarget_ = tail->failure_;
|
||||||
}
|
}
|
||||||
// Remove tail from list
|
// Remove tail from list
|
||||||
predicateStackTail_ = lastNode;
|
predicateStackTail_ = lastNode;
|
||||||
lastNode->next_ = nullptr;
|
lastNode->next_ = JSONCPP_NULL;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +149,9 @@ void TestResult::printFailure(bool printTestName) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print in reverse to display the callstack in the right order
|
// Print in reverse to display the callstack in the right order
|
||||||
for (const auto& failure : failures_) {
|
for (Failures::const_iterator it = failures_.begin(); it != failures_.end();
|
||||||
|
++it) {
|
||||||
|
const Failure& failure = *it;
|
||||||
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
||||||
if (failure.file_) {
|
if (failure.file_) {
|
||||||
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
||||||
@@ -181,7 +185,7 @@ Json::String TestResult::indentText(const Json::String& text,
|
|||||||
}
|
}
|
||||||
|
|
||||||
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
||||||
if (messageTarget_ != nullptr) {
|
if (messageTarget_ != JSONCPP_NULL) {
|
||||||
messageTarget_->message_ += message;
|
messageTarget_->message_ += message;
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -202,9 +206,9 @@ TestResult& TestResult::operator<<(bool value) {
|
|||||||
// class TestCase
|
// class TestCase
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
TestCase::TestCase() = default;
|
TestCase::TestCase() : result_(JSONCPP_NULL) {}
|
||||||
|
|
||||||
TestCase::~TestCase() = default;
|
TestCase::~TestCase() {}
|
||||||
|
|
||||||
void TestCase::run(TestResult& result) {
|
void TestCase::run(TestResult& result) {
|
||||||
result_ = &result;
|
result_ = &result;
|
||||||
@@ -214,7 +218,7 @@ void TestCase::run(TestResult& result) {
|
|||||||
// class Runner
|
// class Runner
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Runner::Runner() = default;
|
Runner::Runner() {}
|
||||||
|
|
||||||
Runner& Runner::add(TestCaseFactory factory) {
|
Runner& Runner::add(TestCaseFactory factory) {
|
||||||
tests_.push_back(factory);
|
tests_.push_back(factory);
|
||||||
@@ -267,19 +271,19 @@ bool Runner::runAllTest(bool printSummary) const {
|
|||||||
printf("All %zu tests passed\n", count);
|
printf("All %zu tests passed\n", count);
|
||||||
}
|
}
|
||||||
return true;
|
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 (size_t index = 0; index < failures.size(); ++index) {
|
||||||
|
TestResult& result = failures[index];
|
||||||
|
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 {
|
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
|
||||||
@@ -308,7 +312,8 @@ int Runner::runCommandLine(int argc, const char* argv[]) const {
|
|||||||
if (opt == "--list-tests") {
|
if (opt == "--list-tests") {
|
||||||
listTests();
|
listTests();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (opt == "--test-auto") {
|
}
|
||||||
|
if (opt == "--test-auto") {
|
||||||
preventDialogOnCrash();
|
preventDialogOnCrash();
|
||||||
} else if (opt == "--test") {
|
} else if (opt == "--test") {
|
||||||
++index;
|
++index;
|
||||||
|
@@ -61,7 +61,7 @@ public:
|
|||||||
/// Not encapsulated to prevent step into when debugging failed assertions
|
/// Not encapsulated to prevent step into when debugging failed assertions
|
||||||
/// Incremented by one on assertion predicate entry, decreased by one
|
/// Incremented by one on assertion predicate entry, decreased by one
|
||||||
/// by addPredicateContext().
|
/// by addPredicateContext().
|
||||||
PredicateContext::Id predicateId_{1};
|
PredicateContext::Id predicateId_;
|
||||||
|
|
||||||
/// \internal Implementation detail for predicate macros
|
/// \internal Implementation detail for predicate macros
|
||||||
PredicateContext* predicateStackTail_;
|
PredicateContext* predicateStackTail_;
|
||||||
@@ -70,7 +70,7 @@ public:
|
|||||||
|
|
||||||
/// Adds an assertion failure.
|
/// Adds an assertion failure.
|
||||||
TestResult& addFailure(const char* file, unsigned int line,
|
TestResult& addFailure(const char* file, unsigned int line,
|
||||||
const char* expr = nullptr);
|
const char* expr = JSONCPP_NULL);
|
||||||
|
|
||||||
/// Removes the last PredicateContext added to the predicate stack
|
/// Removes the last PredicateContext added to the predicate stack
|
||||||
/// chained list.
|
/// chained list.
|
||||||
@@ -84,7 +84,9 @@ public:
|
|||||||
// Generic operator that will work with anything ostream can deal with.
|
// Generic operator that will work with anything ostream can deal with.
|
||||||
template <typename T> TestResult& operator<<(const T& value) {
|
template <typename T> TestResult& operator<<(const T& value) {
|
||||||
Json::OStringStream oss;
|
Json::OStringStream oss;
|
||||||
oss << std::setprecision(16) << std::hexfloat << value;
|
oss.precision(16);
|
||||||
|
oss.setf(std::ios_base::floatfield);
|
||||||
|
oss << value;
|
||||||
return addToLastFailure(oss.str());
|
return addToLastFailure(oss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,9 +108,9 @@ private:
|
|||||||
Failures failures_;
|
Failures failures_;
|
||||||
Json::String name_;
|
Json::String name_;
|
||||||
PredicateContext rootPredicateNode_;
|
PredicateContext rootPredicateNode_;
|
||||||
PredicateContext::Id lastUsedPredicateId_{0};
|
PredicateContext::Id lastUsedPredicateId_;
|
||||||
/// Failure which is the target of the messages added using operator <<
|
/// Failure which is the target of the messages added using operator <<
|
||||||
Failure* messageTarget_{nullptr};
|
Failure* messageTarget_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TestCase {
|
class TestCase {
|
||||||
@@ -122,7 +124,7 @@ public:
|
|||||||
virtual const char* testName() const = 0;
|
virtual const char* testName() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
TestResult* result_{nullptr};
|
TestResult* result_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void runTestCase() = 0;
|
virtual void runTestCase() = 0;
|
||||||
@@ -159,8 +161,8 @@ public:
|
|||||||
static void printUsage(const char* appName);
|
static void printUsage(const char* appName);
|
||||||
|
|
||||||
private: // prevents copy construction and assignment
|
private: // prevents copy construction and assignment
|
||||||
Runner(const Runner& other) = delete;
|
Runner(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||||
Runner& operator=(const Runner& other) = delete;
|
Runner& operator=(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void listTests() const;
|
void listTests() const;
|
||||||
@@ -207,7 +209,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
/// The predicate may do other assertions and be a member function of the
|
/// The predicate may do other assertions and be a member function of the
|
||||||
/// fixture.
|
/// fixture.
|
||||||
#define JSONTEST_ASSERT_PRED(expr) \
|
#define JSONTEST_ASSERT_PRED(expr) \
|
||||||
{ \
|
do { \
|
||||||
JsonTest::PredicateContext _minitest_Context = { \
|
JsonTest::PredicateContext _minitest_Context = { \
|
||||||
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
|
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
|
||||||
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
||||||
@@ -215,7 +217,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
result_->predicateStackTail_ = &_minitest_Context; \
|
result_->predicateStackTail_ = &_minitest_Context; \
|
||||||
(expr); \
|
(expr); \
|
||||||
result_->popPredicateContext(); \
|
result_->popPredicateContext(); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
/// \brief Asserts that two values are equals.
|
/// \brief Asserts that two values are equals.
|
||||||
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
|
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
|
||||||
@@ -230,7 +232,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
|
|
||||||
/// \brief Asserts that a given expression throws an exception
|
/// \brief Asserts that a given expression throws an exception
|
||||||
#define JSONTEST_ASSERT_THROWS(expr) \
|
#define JSONTEST_ASSERT_THROWS(expr) \
|
||||||
{ \
|
do { \
|
||||||
bool _threw = false; \
|
bool _threw = false; \
|
||||||
try { \
|
try { \
|
||||||
expr; \
|
expr; \
|
||||||
@@ -240,7 +242,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
if (!_threw) \
|
if (!_threw) \
|
||||||
result_->addFailure(__FILE__, __LINE__, \
|
result_->addFailure(__FILE__, __LINE__, \
|
||||||
"expected exception thrown: " #expr); \
|
"expected exception thrown: " #expr); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
/// \brief Begin a fixture test case.
|
/// \brief Begin a fixture test case.
|
||||||
#define JSONTEST_FIXTURE(FixtureType, name) \
|
#define JSONTEST_FIXTURE(FixtureType, name) \
|
||||||
@@ -251,8 +253,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
public: /* overridden from TestCase */ \
|
public: /* overridden from TestCase */ \
|
||||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
const char* testName() const JSONCPP_OVERRIDE { \
|
||||||
void runTestCase() override; \
|
return #FixtureType "/" #name; \
|
||||||
|
} \
|
||||||
|
void runTestCase() JSONCPP_OVERRIDE; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
void Test##FixtureType##name::runTestCase()
|
void Test##FixtureType##name::runTestCase()
|
||||||
@@ -276,8 +280,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
public: /* overridden from TestCase */ \
|
public: /* overridden from TestCase */ \
|
||||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
const char* testName() const JSONCPP_OVERRIDE { \
|
||||||
void runTestCase() override; \
|
return #FixtureType "/" #name; \
|
||||||
|
} \
|
||||||
|
void runTestCase() JSONCPP_OVERRIDE; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
static bool test##FixtureType##name##collect = \
|
static bool test##FixtureType##name##collect = \
|
||||||
|
File diff suppressed because it is too large
Load Diff
1
test/data/fail_test_array_02.json
Normal file
1
test/data/fail_test_array_02.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[1,,]
|
1
test/data/fail_test_object_01.json
Normal file
1
test/data/fail_test_object_01.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ "count" : 1234,, }
|
2
test/data/test_array_08.expected
Normal file
2
test/data/test_array_08.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.=[]
|
||||||
|
.[0]=1
|
1
test/data/test_array_08.json
Normal file
1
test/data/test_array_08.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[1,]
|
2
test/data/test_object_05.expected
Normal file
2
test/data/test_object_05.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.={}
|
||||||
|
.count=1234
|
1
test/data/test_object_05.json
Normal file
1
test/data/test_object_05.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ "count" : 1234, }
|
@@ -62,6 +62,10 @@ def safeReadFile(path):
|
|||||||
except IOError as e:
|
except IOError as e:
|
||||||
return '<File "%s" is missing: %s>' % (path,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,
|
def runAllTests(jsontest_executable_path, input_dir = None,
|
||||||
use_valgrind=False, with_json_checker=False,
|
use_valgrind=False, with_json_checker=False,
|
||||||
writerClass='StyledWriter'):
|
writerClass='StyledWriter'):
|
||||||
@@ -69,45 +73,26 @@ def runAllTests(jsontest_executable_path, input_dir = None,
|
|||||||
input_dir = os.path.join(os.getcwd(), 'data')
|
input_dir = os.path.join(os.getcwd(), 'data')
|
||||||
tests = glob(os.path.join(input_dir, '*.json'))
|
tests = glob(os.path.join(input_dir, '*.json'))
|
||||||
if with_json_checker:
|
if with_json_checker:
|
||||||
all_test_jsonchecker = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
|
all_tests = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
|
||||||
# These tests fail with strict json support, but pass with jsoncpp extra lieniency
|
# These tests fail with strict json support, but pass with JsonCPP's
|
||||||
"""
|
# extra leniency features. When adding a new exclusion to this list,
|
||||||
Failure details:
|
# remember to add the test's number and reasoning here:
|
||||||
* Test ../jsonchecker/fail25.json
|
known = ["fail{}.json".format(n) for n in [
|
||||||
Parsing should have failed:
|
4, 9, # fail because we allow trailing commas
|
||||||
[" tab character in string "]
|
7, # fails because we allow commas after close
|
||||||
|
8, # fails because we allow extra close
|
||||||
* Test ../jsonchecker/fail13.json
|
10, # fails because we allow extra values after close
|
||||||
Parsing should have failed:
|
13, # fails because we allow leading zeroes in numbers
|
||||||
{"Numbers cannot have leading zeroes": 013}
|
18, # fails because we allow deeply nested values
|
||||||
|
25, # fails because we allow tab characters in strings
|
||||||
* Test ../jsonchecker/fail18.json
|
27, # fails because we allow string line breaks
|
||||||
Parsing should have failed:
|
]]
|
||||||
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
|
test_jsonchecker = [ test for test in all_tests
|
||||||
|
if os.path.basename(test) not in known]
|
||||||
* 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 ]
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
test_jsonchecker = []
|
test_jsonchecker = []
|
||||||
|
|
||||||
failed_tests = []
|
failed_tests = []
|
||||||
valgrind_path = use_valgrind and VALGRIND_CMD or ''
|
valgrind_path = use_valgrind and VALGRIND_CMD or ''
|
||||||
for input_path in tests + test_jsonchecker:
|
for input_path in tests + test_jsonchecker:
|
||||||
@@ -161,10 +146,9 @@ def runAllTests(jsontest_executable_path, input_dir = None,
|
|||||||
print()
|
print()
|
||||||
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
|
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
|
||||||
len(failed_tests)))
|
len(failed_tests)))
|
||||||
return 1
|
raise FailError(repr(failed_tests))
|
||||||
else:
|
else:
|
||||||
print('All %d tests passed.' % len(tests))
|
print('All %d tests passed.' % len(tests))
|
||||||
return 0
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
@@ -187,24 +171,21 @@ def main():
|
|||||||
input_path = os.path.normpath(os.path.abspath(args[1]))
|
input_path = os.path.normpath(os.path.abspath(args[1]))
|
||||||
else:
|
else:
|
||||||
input_path = None
|
input_path = None
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledWriter')
|
writerClass='StyledWriter')
|
||||||
if status:
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
sys.exit(status)
|
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledStreamWriter')
|
writerClass='StyledStreamWriter')
|
||||||
if status:
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
sys.exit(status)
|
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='BuiltStyledStreamWriter')
|
writerClass='BuiltStyledStreamWriter')
|
||||||
if status:
|
|
||||||
sys.exit(status)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
try:
|
||||||
|
main()
|
||||||
|
except FailError:
|
||||||
|
sys.exit(1)
|
||||||
|
Reference in New Issue
Block a user