Compare commits

...

51 Commits

Author SHA1 Message Date
chenguoping
7c186e549f update README 2020-04-30 15:05:27 +08:00
chenguoping
d9ffdc4bcb Configure Travis CI, to extend more compile environments.
Revert commit 9e5d57c to support string tpye VERSION.
Add cmake compilation switch to choose language stanard.
2020-04-30 14:59:08 +08:00
chenguoping
d2c205206d Rewrite and revert some code to build in pre-C++11
Rewerite and revert some code that this library can be built in pre-C++11 and C++11 env.
Main Change List:
1. using -> typedef
2. not using auto & decltype
3. not using raw string literals
4. ..., other c++11 features will be chosen to compile, depending on env.
2020-04-30 11:24:36 +08:00
xkszltl
a4fb5db543 Put ".exe" and ".dll" together to make test usable in build dir. (#1166) 2020-04-30 10:31:54 +08:00
Christopher Dunn
d517d598a7 Merge pull request #1165 from mrjoel/mrjoel/cmake-updates
Improve CMake correctness and handling
2020-04-29 08:27:43 -05:00
Joel Johnson
e9b0b96be6 Remove redundant cmake_minimum_required from example
This is already covered by the toplevel CMake, which also serves to
provide a consistent minimum version.
2020-04-28 15:21:16 -06:00
Joel Johnson
3f0d63b5a9 Use internal CMake compiler version directly 2020-04-28 15:21:16 -06:00
Joel Johnson
524234e479 Use non-version checked add_compile_options
Commit aebc7fa added version checks for CMake compatibility. In reality,
only the add_compile_definitions need the check - add_compile_options
itself has been supported since 3.0. Tested and confirmed built
successfully with CMake 3.8.0.
2020-04-28 15:21:16 -06:00
Joel Johnson
9abf11935c Remove unused CMake variable
EXTRA_CXX_FLAGS is never defined, making this a noop. Further,
COMPILE_OPTIONS is invalid to set as a DIRECTORY property.
2020-04-28 15:21:16 -06:00
Joel Johnson
8a5e792f20 Add Clang support, be explicit about MSVC flags 2020-04-28 15:21:16 -06:00
Joel Johnson
30eb5ce128 Check compiler using CMAKE_CXX_COMPILER_ID
Since the introduction of CMAKE_COMPILER_IS_GNUCXX CMake has
suggested using CMAKE_CXX_COMPILER_ID for more general checks.
2020-04-28 15:21:16 -06:00
Joel Johnson
12ceb01485 Always use consistent CXX_STANDARD
Since CMake has subdirectory variable scope, unilaterally set the
CMAKE_CXX_STANDARD variable to use C++11. This covers cases with the
library being included externally, both in cases of only C++98 being
specified, as well as later versions being specified (since the
CXX_STANDARD itself isn't a library dependency, only the PUBLIC
target_compile_features on jsoncpp_lib). The previous direct check for
C++98 is handled by requiring C++11 on this library; should the
compiler being used not support C++11 then CMake will issue an error.
2020-04-28 15:21:16 -06:00
Joel Johnson
edc6239f39 Not needed to specify CMAKE_MACOSX_RPATH
As of CMake 3.0 with CMP0042, MACOSX_RPATH is enabled by default.
Since the validated version used by jsoncpp is later than 3.0,
this is already covered.
2020-04-28 15:21:16 -06:00
Joel Johnson
5a0152ae1b Only set CMAKE_BUILD_TYPE for single config generators 2020-04-28 15:21:16 -06:00
Joel Johnson
c648b0378a Consolidate setting of jsoncpp target properties 2020-04-28 15:21:16 -06:00
Joel Johnson
a3afd74b80 Don't use unique variable for postfix
The more general CMake way to handle library suffixing is to set
CMAKE_<CONFIG>_POSTFIX, so setting the Debug output suffix name should
be more correctly done by the caller or CMake configurer by setting
the desired value in CMAKE_DEBUG_POSTFIX.
2020-04-28 15:21:16 -06:00
Chen
2cb16b35dc allowBom -> skipBom (#1162) 2020-04-28 17:30:08 +08:00
Chen
83946a28db Ignore byte order mark in the head of UTF-8 text. (#1149)
* Ignore bom at the beginning of the UTF-8 text
2020-04-28 15:16:05 +08:00
bcsgh
91f1553f2c Make throwRuntimeError/throwLogicError print msg when built with JSON_USE_EXCEPTION=0 2020-04-24 13:40:51 -05:00
Christopher Dunn
5813ab1bc1 Merge branch 'fixup-tests' into 'master' (#1102) 2020-04-24 13:06:44 -05:00
Christopher Dunn
a0b8c3ecb4 Do not run colliding tests at same time 2020-04-24 12:43:17 -05:00
Jordan Bayles
b349221938 Cleanup test configurations 2020-04-24 12:43:17 -05:00
Jordan Bayles
9e23f66f61 Issue 1102: Fixup test suite, fix broken tests
A recent PR broken the JsonChecker tests by adding support for trailing
commas. This didn't end up breaking the build, because those tests
aren't run, except locally and only using CMake.

This patch fixes the tests by adding exclusions for trailing comma
tests, as well as updates Meson to run these tests as part of `ninja
test`.

See issue #1102.
2020-04-24 12:43:17 -05:00
Christopher Dunn
411d88fae8 Stop checking status; raise instead 2020-04-24 12:43:17 -05:00
Christopher Dunn
1ff6bb65a0 ninja test 2020-04-24 12:43:17 -05:00
Ben Boeckel
8b20b7a317 amalgamate: add version.h and allocator.h to the forwards header
Required to get JSONCPP_USING_SECURE_MEMORY and the SecureAllocator
available for the definition of Allocator.
2020-04-23 23:22:10 -05:00
Stefano Fiorentino
2e54e8ff1c adding myself to AUTHORS as per commits (#1109)
commits:
ff923658c4
5907cef86c
2020-04-23 22:52:56 -05:00
Rosen Penev
90ca694e46 clang-tidy fixes again (#1155)
* [clang-tidy] remove redundant string initialization

Found with readability-redundant-string-init

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* [clang-tidy] switch to raw strings

Easier to read.

Found with modernize-raw-string-literal

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* [clang-tidy] fix performance issues

Found with performance*

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* fix extra comma warnings

Found with clang's -Wextra-semi-stmt

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* remove JSONCPP_OP_EXPLICIT

This codebase in C++11. No need for compatibility with C++98.

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* remove JSONCPP_NOEXCEPT

This codebase is C++11 now. No need for this macro.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
2020-04-12 01:26:04 -04:00
Chen
3beb37ea14 revert trailing comma in old Reader (#1126) 2020-02-13 13:25:08 -08:00
David Gobbi
dc180eb25e Remove '=delete' from template methods for Xcode 8 (#1133)
For Apple clang-800.0.42.1, which was released with Xcode 8 in
September 2016, the '=delete' on the 'is' and 'as' methods causes
the following errors for value.h:

  inline declaration of 'as<bool>' follows non-inline definition
  inline declaration of 'is<bool>' follows non-inline definition

etcetera for the other specializations of 'is' and 'as'.  The same
problem also occurs for clang-3.8 but not clang-3.9 or later.
2020-02-13 13:22:49 -08:00
Claus Klein
a6fe8e27d8 Use ccache right (#1139)
* Prevent cmakelint warnings

Use 4 spaces for indent, no tabs

* Use ccache right

fix indents too at CMakeLists.txt
2020-02-13 13:20:46 -08:00
Rosen Penev
edf528edfa clang-tidy fixes again (#1087)
* [clang-tidy] Do not use else after return

Found with readability-else-after-return

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* [clang-tidy] Convert several loops to be range based

Found with modernize-loop-convert

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* [clang-tidy] Replace deprecated C headers

Found with modernize-deprecated-headers

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* [clang-tidy] Use auto where applicable

Found with modernize-use-auto

Signed-off-by: Rosen Penev <rosenp@gmail.com>

* .clang-tidy: Add these checks
2020-02-02 23:03:45 -05:00
Chen
6317f9a406 fix compile warnning using cmake (#1132) 2020-01-20 17:12:35 +08:00
David Seifert
6bc55ec35d Meson updates (#1124)
* Modernize meson.build

* Make tests optional
* Use `files()` for quick sanity checks

* Bump version to 1.9.3

* Bump SOVERSION, as some functions were removed
  and structs were changed, as determined by
  libabigail.
2020-01-07 09:23:50 +08:00
Andrew Childs
f11611c878 json_writer: fix inverted sense in isAnyCharRequiredQuoting (#1120)
This bug is only affects platforms where `char` is unsigned.

When char is a signed type, values >= 0x80 are also considered < 0,
and hence require escaping due to the < ' ' condition.

When char is an unsigned type, values >= 0x80 match none of the
conditions and are considered safe to emit without escaping.

This shows up as a test failure:

* Detail of EscapeSequenceTest/writeEscapeSequence test failure:
/build/source/src/test_lib_json/main.cpp(3370): expected == result
  Expected: '["\"","\\","\b","\f","\n","\r","\t","\u0278","\ud852\udf62"]
  '
  Actual  : '["\"","\\","\b","\f","\n","\r","\t","ɸ","𤭢"]
  '
2019-12-28 15:04:24 +08:00
Chen
8f7f35c5cd Replace Raw Unicode in Testcase (#1127)
* use unicode code point

* change values' order, because JSONTEST_ASSERT_EQUAL(expected, actual)
2019-12-26 16:08:17 +08:00
theirix
7e5485ab5b Add option JSONCPP_WITH_EXAMPLE (#1099)
* Add option JSONCPP_WITH_EXAMPLE

Allows to conditionally build examples as
it has been done for tests.  Useful for packaging.

* Do not build example by default
2019-12-23 11:04:44 +08:00
Chen
92d90250f2 fix Reader bug and add testcase (#1122) 2019-12-23 10:56:54 +08:00
Billy Donahue
d6c4a8fb2d tweak to avoid implicit narrowing warning. (#1114)
* tweak to avoid implicit narrowing warning.

change an int to size_t #1113

* Update main.cpp
2019-12-11 12:12:37 -08:00
Chen
a3c8642886 Add test cases for Reader (#1108)
* update testcase for reader

* add a helper function

* refactor structured error testing
2019-12-04 10:24:52 +08:00
Chen
2983f5a89a Run Clang-tidy with modernize-use-auto (#1077)
* Run clang-tidy modify with modernize-use-auto
* Use using instead of typedef
2019-12-04 09:08:45 +08:00
Chen
a0bd9adfef Add an insert overload function (#1110) 2019-12-03 09:13:42 +08:00
Billy Donahue
9e0d70aa66 eliminate some redundancy in test_lib_json/main.cpp (#1104)
refactor test 'CharReaderAllowDropNullTest/issue178'
2019-11-15 09:18:32 -05:00
dota17
f200239d5b Add some testcases for charReader (#1095)
* update charReader test case

* remove C ++ compiler version switch for smart pointer

* remove comma test due to PR #1098
2019-11-15 14:51:43 +08:00
Christopher Dunn
cfc3e927fc Merge pull request #1101 from open-source-parsers/drop_cpptl_support
Issue 1100: Drop CPPTL support
2019-11-15 00:31:06 -06:00
Jordan Bayles
a481201af1 Readd some overzealously removed code 2019-11-14 10:21:15 -08:00
Jordan Bayles
9704cedb20 Issue 1100: Drop CPPTL support
CPPTL support is no longer relevant to JsonCpp, and can be removed from
the library. This patch removes all mentions of CPPTL, by removing all
definitions and code sections conditionally compiled only when JsonCpp
is used with CPPTL. Include guards are also renamed to not refer to
CPPTL where appropriate.
2019-11-14 09:38:11 -08:00
Christopher Dunn
781eec4da8 Merge pull request #1098 from cdunn2001/allow-trailing-commas
Allow trailing comma in objects and arrays
2019-11-14 00:21:18 -06:00
Jacob Bundgaard
1c8f7d8ae5 Run clang-format 2019-11-14 00:05:24 -06:00
Jacob Bundgaard
554d961625 Allow trailing comma in arrays if dropped null placeholders are not allowed 2019-11-14 00:05:24 -06:00
Jacob Bundgaard
01db7b7430 Allow trailing comma in objects 2019-11-14 00:05:24 -06:00
45 changed files with 1653 additions and 1242 deletions

View File

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

View File

@@ -9,18 +9,18 @@ sudo: false
addons:
homebrew:
packages:
- clang-format
- meson
- ninja
- clang-format
- meson
- ninja
update: false # do not update homebrew by default
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
- ubuntu-toolchain-r-test
- llvm-toolchain-xenial-8
packages:
- clang-format-8
- clang-8
- valgrind
- clang-format-8
- clang-8
- valgrind
matrix:
allow_failures:
- os: osx
@@ -30,27 +30,74 @@ matrix:
osx_image: xcode11
compiler: clang
env:
CXX="clang++"
CC="clang"
LIB_TYPE=static
BUILD_TYPE=release
CXX="clang++"
CC="clang"
LIB_TYPE=static
BUILD_TYPE=release
LANGUAGE_STANDARD="11"
script: ./.travis_scripts/meson_builder.sh
- name: Linux xenial clang meson static release testing
os: linux
dist: xenial
compiler: clang
env:
CXX="clang++"
CC="clang"
LIB_TYPE=static
BUILD_TYPE=release
CXX="clang++"
CC="clang"
LIB_TYPE=static
BUILD_TYPE=release
LANGUAGE_STANDARD="11"
# before_install and install steps only needed for linux meson builds
before_install:
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
- source ./.travis_scripts/travis.before_install.${TRAVIS_OS_NAME}.sh
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
- 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
dist: xenial
compiler: gcc
@@ -62,10 +109,77 @@ matrix:
BUILD_TYPE=Debug
LIB_TYPE=shared
DESTDIR=/tmp/cmake_json_cpp
LANGUAGE_STANDARD="11"
before_install:
- pip install --user cpp-coveralls
- pip install --user cpp-coveralls
script: ./.travis_scripts/cmake_builder.sh
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:
email: false

View File

@@ -66,7 +66,7 @@ cmake --version
echo ${CXX}
${CXX} --version
_COMPILER_NAME=`basename ${CXX}`
if [ "${BUILD_TYPE}" == "shared" ]; then
if [ "${BUILD_TYPE}" = "shared" ]; then
_CMAKE_BUILD_SHARED_LIBS=ON
else
_CMAKE_BUILD_SHARED_LIBS=OFF
@@ -98,6 +98,14 @@ else
export _BUILD_EXE=make
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}"
mkdir -p ${_BUILD_DIR_NAME}
cd "${_BUILD_DIR_NAME}"
@@ -112,6 +120,7 @@ cd "${_BUILD_DIR_NAME}"
-DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} \
-DBUILD_SHARED_LIBS:BOOL=${_CMAKE_BUILD_SHARED_LIBS} \
-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

View File

@@ -64,11 +64,15 @@ ninja --version
_COMPILER_NAME=`basename ${CXX}`
_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
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}"
meson configure -Dcpp_std="c++${_CPP_STD}"
ninja -v -j 2 -C ./
meson test --no-rebuild --print-errorlogs
if [ "${DESTDIR}" != "/usr/local" ]; then

View File

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

View File

@@ -37,44 +37,63 @@ foreach(pold "") # Currently Empty
endif()
endforeach()
# ==== Define language standard configurations requiring at least c++11 standard
if(CMAKE_CXX_STANDARD EQUAL "98" )
message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported.")
endif()
#####
## Set the default target properties
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11) # Supported values are ``11``, ``14``, and ``17``.
endif()
if(NOT CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
# ====
# Ensures that CMAKE_BUILD_TYPE has a default value
if(NOT DEFINED CMAKE_BUILD_TYPE)
# Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
endif()
# ---------------------------------------------------------------------------
# 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
# 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)
# 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}")
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_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_PKGCONFIG_SUPPORT "Generate and install .pc 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_WITH_CXX_11 "Build jsoncpp_lib with C++11 standard." ON)
# Enable runtime search path support for dynamic libraries on OSX
if(APPLE)
set(CMAKE_MACOSX_RPATH 1)
## To compatible with C++0x and C++1x
set(CMAKE_MINIMUN_CXX_STANDARD 98)
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()
# Adhere to GNU filesystem layout conventions
include(GNUInstallDirs)
set(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build")
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Archive output dir.")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Library output dir.")
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "PDB (MSVC debug symbol)output dir.")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL" )
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL")
configure_file( "${PROJECT_SOURCE_DIR}/version.in"
"${PROJECT_BINARY_DIR}/version"
NEWLINE_STYLE UNIX )
configure_file("${PROJECT_SOURCE_DIR}/version.in"
"${PROJECT_BINARY_DIR}/version"
NEWLINE_STYLE UNIX)
macro(UseCompilationWarningAsError)
macro(use_compilation_warning_as_error)
if(MSVC)
# Only enabled in debug because some old versions of VS STL generate
# warnings when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/WX>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
endif()
add_compile_options($<$<CONFIG:Debug>:/WX>)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
add_compile_options(-Werror)
if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic-errors)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
endif()
endif()
endif()
endmacro()
# Include our configuration header
include_directories( ${jsoncpp_SOURCE_DIR}/include )
include_directories(${jsoncpp_SOURCE_DIR}/include)
if(MSVC)
# Only enabled in debug because some old versions of VS STL generate
# unreachable code warning when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/W4>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
endif()
add_compile_options($<$<CONFIG:Debug>:/W4>)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# using GCC
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
# not yet ready for -Wsign-conversion
if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
add_compile_options(-Wall)
endif()
if(JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
endif()
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
# using Intel compiler
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
endif()
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
add_compile_options(-Wpedantic)
endif()
endif()
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)
if(JSONCPP_WITH_WARNING_AS_ERROR)
UseCompilationWarningAsError()
use_compilation_warning_as_error()
endif()
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
@@ -205,27 +207,29 @@ if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
endif()
if(JSONCPP_WITH_CMAKE_PACKAGE)
include (CMakePackageConfigHelpers)
install(EXPORT jsoncpp
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
FILE jsoncppConfig.cmake)
write_basic_package_version_file ("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
include(CMakePackageConfigHelpers)
install(EXPORT jsoncpp
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
FILE jsoncppConfig.cmake)
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
VERSION ${JSONCPP_VERSION}
COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
endif()
if(JSONCPP_WITH_TESTS)
enable_testing()
include(CTest)
enable_testing()
include(CTest)
endif()
# Build the different applications
add_subdirectory( src )
add_subdirectory(src)
#install the includes
add_subdirectory( include )
add_subdirectory(include)
#install the example
add_subdirectory( example )
if(JSONCPP_WITH_EXAMPLE)
add_subdirectory(example)
endif()

View File

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

View File

@@ -1,11 +1,5 @@
# JsonCpp
[![badge](https://img.shields.io/badge/conan.io-jsoncpp%2F1.8.0-green.svg?logo=data:image/png;base64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAA1VBMVEUAAABhlctjlstkl8tlmMtlmMxlmcxmmcxnmsxpnMxpnM1qnc1sn85voM91oM11oc1xotB2oc56pNF6pNJ2ptJ8ptJ8ptN9ptN8p9N5qNJ9p9N9p9R8qtOBqdSAqtOAqtR%2BrNSCrNJ/rdWDrNWCsNWCsNaJs9eLs9iRvNuVvdyVv9yXwd2Zwt6axN6dxt%2Bfx%2BChyeGiyuGjyuCjyuGly%2BGlzOKmzOGozuKoz%2BKqz%2BOq0OOv1OWw1OWw1eWx1eWy1uay1%2Baz1%2Baz1%2Bez2Oe02Oe12ee22ujUGwH3AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgBQkREyOxFIh/AAAAiklEQVQI12NgAAMbOwY4sLZ2NtQ1coVKWNvoc/Eq8XDr2wB5Ig62ekza9vaOqpK2TpoMzOxaFtwqZua2Bm4makIM7OzMAjoaCqYuxooSUqJALjs7o4yVpbowvzSUy87KqSwmxQfnsrPISyFzWeWAXCkpMaBVIC4bmCsOdgiUKwh3JojLgAQ4ZCE0AMm2D29tZwe6AAAAAElFTkSuQmCC)](https://bintray.com/theirix/conan-repo/jsoncpp%3Atheirix)
[![badge](https://img.shields.io/badge/license-MIT-blue)](https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE)
[![badge](https://img.shields.io/badge/document-doxygen-brightgreen)](http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html)
[![Coverage Status](https://coveralls.io/repos/github/open-source-parsers/jsoncpp/badge.svg?branch=master)](https://coveralls.io/github/open-source-parsers/jsoncpp?branch=master)
[JSON][json-org] is a lightweight data-interchange format. It can represent
numbers, strings, ordered sequences of values, and collections of name/value
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
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
@@ -30,6 +31,7 @@ format to store user input files.
* `1.y.z` is built with C++11.
* `0.y.z` can be used with older compilers.
* `00.11.z` can be used with older compilers , with new features from `1.y.z`
* Major versions maintain binary-compatibility.

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
#include "json/json.h"
#include <cstdlib>
#include <fstream>
#include <iostream>
/** \brief Parse from stream, collect comments and capture error info.

View File

@@ -1,4 +1,5 @@
#include "json/json.h"
#include <cstdlib>
#include <iostream>
/**
* \brief Parse a raw string into Value object using the CharReaderBuilder
@@ -10,9 +11,9 @@
* 20
*/
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());
constexpr bool shouldUseOldWay = false;
JSONCPP_CONST bool shouldUseOldWay = false;
JSONCPP_STRING err;
Json::Value root;
@@ -21,12 +22,13 @@ int main() {
reader.parse(rawJson, root);
} else {
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,
&err)) {
std::cout << "error" << std::endl;
return EXIT_FAILURE;
}
delete reader;
}
const std::string name = root["Name"].asString();
const int age = root["Age"].asInt();

View File

@@ -12,11 +12,11 @@
int main() {
Json::Value root;
Json::StreamWriterBuilder builder;
const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
Json::StreamWriter* writer(builder.newStreamWriter());
root["Name"] = "robin";
root["Age"] = 20;
writer->write(root, &std::cout);
delete writer;
return EXIT_SUCCESS;
}

View File

@@ -1,4 +1,5 @@
#include "json/json.h"
#include <cstdlib>
#include <iostream>
/** \brief Write a Value object to a string.
* Example Usage:
@@ -15,7 +16,7 @@
int main() {
Json::Value root;
Json::Value data;
constexpr bool shouldUseOldWay = false;
JSONCPP_CONST bool shouldUseOldWay = false;
root["action"] = "run";
data["number"] = 1;
root["data"] = data;

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
#ifndef JSON_ALLOCATOR_H_INCLUDED
#define JSON_ALLOCATOR_H_INCLUDED
#include <cstring>
#include <memory>
@@ -86,4 +86,4 @@ bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
#pragma pack(pop)
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
#endif // JSON_ALLOCATOR_H_INCLUDED

View File

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

View File

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

View File

@@ -5,24 +5,20 @@
#ifndef JSON_CONFIG_H_INCLUDED
#define JSON_CONFIG_H_INCLUDED
#include <cstddef>
#include <cstdint>
#include <istream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <type_traits>
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
#if JSONCPP_CXX_STD_11
#include <cstddef> // typedef ptrdiff_t
#include <cstdint> // typedef int64_t, uint64_t
#else
#include <stddef.h>
#include <stdint.h>
#endif
// If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions.
@@ -40,37 +36,26 @@
/// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL
#include <cpptl/config.h>
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
// Export macros for DLL visibility
#if defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER)
#elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL
#endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API)
#define JSON_API
#endif
#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
// As recommended at
// 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.
// #define JSON_NO_INT64 1
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
// 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
#if __cplusplus >= 201103L || defined(_MSC_VER)
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT
#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__
#if __has_extension(attribute_deprecated_with_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
#if !defined(JSON_IS_AMALGAMATION)
#if JSONCPP_CXX_STD_11
#include "allocator.h"
#endif
#include "version.h"
#endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json {
typedef int Int;
typedef unsigned int UInt;
#if defined(JSON_NO_INT64)
@@ -155,6 +159,7 @@ typedef UInt64 LargestUInt;
#define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64)
#if JSONCPP_CXX_STD_11
template <typename T>
using Allocator =
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
@@ -168,13 +173,20 @@ using OStringStream =
String::allocator_type>;
using IStream = std::istream;
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
// Legacy names (formerly macros).
using JSONCPP_STRING = Json::String;
using JSONCPP_ISTRINGSTREAM = Json::IStringStream;
using JSONCPP_OSTRINGSTREAM = Json::OStringStream;
using JSONCPP_ISTREAM = Json::IStream;
using JSONCPP_OSTREAM = Json::OStream;
typedef Json::String JSONCPP_STRING;
typedef Json::IStringStream JSONCPP_ISTRINGSTREAM;
typedef Json::OStringStream JSONCPP_OSTRINGSTREAM;
typedef Json::IStream JSONCPP_ISTREAM;
typedef Json::OStream JSONCPP_OSTREAM;
#endif // JSON_CONFIG_H_INCLUDED

View File

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

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
#define CPPTL_JSON_FEATURES_H_INCLUDED
#ifndef JSON_FEATURES_H_INCLUDED
#define JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
@@ -41,21 +41,21 @@ public:
Features();
/// \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
/// false.
bool strictRoot_{false};
bool strictRoot_;
/// \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.
bool allowNumericKeys_{false};
bool allowNumericKeys_;
};
} // namespace Json
#pragma pack(pop)
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
#endif // JSON_FEATURES_H_INCLUDED

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_READER_H_INCLUDED
#define CPPTL_JSON_READER_H_INCLUDED
#ifndef JSON_READER_H_INCLUDED
#define JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "json_features.h"
@@ -210,7 +210,8 @@ private:
unsigned int& unicode);
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
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 addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken);
@@ -230,21 +231,21 @@ private:
Nodes nodes_;
Errors errors_;
String document_;
Location begin_{};
Location end_{};
Location current_{};
Location lastValueEnd_{};
Value* lastValue_{};
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value* lastValue_;
String commentsBefore_;
Features features_;
bool collectComments_{};
bool collectComments_;
}; // Reader
/** Interface for reading JSON from a char array.
*/
class JSON_API CharReader {
public:
virtual ~CharReader() = default;
virtual ~CharReader() {}
/** \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 to read.
@@ -266,7 +267,7 @@ public:
class JSON_API Factory {
public:
virtual ~Factory() = default;
virtual ~Factory() {}
/** \brief Allocate a CharReader via operator new().
* \throw std::exception if something goes wrong (e.g. invalid settings)
*/
@@ -299,6 +300,8 @@ public:
* if allowComments is false.
* - `"allowComments": false or true`
* - true if comments are allowed.
* - `"allowTrailingCommas": false or true`
* - true if trailing commas in objects and arrays are allowed.
* - `"strictRoot": false or true`
* - true if root must be either an array or an object value
* - `"allowDroppedNullPlaceholders": false or true`
@@ -330,9 +333,9 @@ public:
Json::Value settings_;
CharReaderBuilder();
~CharReaderBuilder() override;
~CharReaderBuilder() JSONCPP_OVERRIDE;
CharReader* newCharReader() const override;
CharReader* newCharReader() const JSONCPP_OVERRIDE;
/** \return true if 'settings' are legal and consistent;
* otherwise, indicate bad settings via 'invalid'.
@@ -398,4 +401,4 @@ JSON_API IStream& operator>>(IStream&, Value&);
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_READER_H_INCLUDED
#endif // JSON_READER_H_INCLUDED

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_H_INCLUDED
#define CPPTL_JSON_H_INCLUDED
#ifndef JSON_H_INCLUDED
#define JSON_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h"
@@ -13,29 +13,47 @@
// Conditional NORETURN attribute on the throw functions would:
// a) suppress false positives from static code analysis
// b) possibly improve optimization opportunities.
// For compatibility, [[noreturn]] is not used
#if !defined(JSONCPP_NORETURN)
#if defined(_MSC_VER) && _MSC_VER == 1800
#if defined(_MSC_VER)
#define JSONCPP_NORETURN __declspec(noreturn)
#elif defined(__GNUC__) || defined(__clang__)
#define JSONCPP_NORETURN __attribute__((noreturn))
#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
#include <array>
#if JSONCPP_CXX_STD_11
#else
#undef JSONCPP_TEMPLATE_DELETE
#define JSONCPP_TEMPLATE_DELETE
#include <string.h>
#endif
#include <exception>
#include <memory>
#include <map>
#include <string>
#include <vector>
#ifndef JSON_USE_CPPTL_SMALLMAP
#include <map>
#else
#include <cpptl/smallmap.h>
#endif
#ifdef JSON_USE_CPPTL
#include <cpptl/forwards.h>
#endif
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -57,8 +75,8 @@ namespace Json {
class JSON_API Exception : public std::exception {
public:
Exception(String msg);
~Exception() JSONCPP_NOEXCEPT override;
char const* what() const JSONCPP_NOEXCEPT override;
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
protected:
String msg_;
@@ -120,11 +138,6 @@ enum PrecisionType {
decimalPlaces ///< we set max number of digits after "." in string
};
//# ifdef JSON_USE_CPPTL
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
//# endif
/** \brief Lightweight wrapper to tag static string.
*
* Value constructor and objectValue member assignment takes advantage of the
@@ -141,7 +154,7 @@ enum PrecisionType {
*/
class JSON_API StaticString {
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_; }
@@ -215,34 +228,35 @@ public:
static Value const& nullSingleton();
/// 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));
/// 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.
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.
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.
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.
static constexpr UInt maxUInt = UInt(-1);
static JSONCPP_CONST UInt maxUInt = UInt(-1);
#if defined(JSON_HAS_INT64)
/// 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.
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.
static constexpr UInt64 maxUInt64 = UInt64(-1);
static JSONCPP_CONST UInt64 maxUInt64 = UInt64(-1);
#endif // defined(JSON_HAS_INT64)
/// 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
// converting Value::maxUInt64 to a double correctly (AIX/xlC).
// 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
// when using gcc and clang backend compilers. CZString
// cannot be defined as private. See issue #486
@@ -258,11 +272,14 @@ private:
CZString(ArrayIndex index);
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
CZString(CZString const& other);
#if JSONCPP_CXX_STD_11
CZString(CZString&& other);
#endif
~CZString();
CZString& operator=(const CZString& other);
#if JSONCPP_CXX_STD_11
CZString& operator=(CZString&& other);
#endif
bool operator<(CZString const& other) const;
bool operator==(CZString const& other) const;
ArrayIndex index() const;
@@ -287,11 +304,7 @@ private:
};
public:
#ifndef JSON_USE_CPPTL_SMALLMAP
typedef std::map<CZString, Value> ObjectValues;
#else
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
#endif // ifndef JSON_USE_CPPTL_SMALLMAP
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public:
@@ -340,18 +353,19 @@ public:
*/
Value(const StaticString& value);
Value(const String& value);
#ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString& value);
#endif
Value(bool value);
Value(const Value& other);
#if JSONCPP_CXX_STD_11
Value(Value&& other);
#endif
~Value();
/// \note Overwrite existing comments. To preserve comments, use
/// #swapPayload().
Value& operator=(const Value& other);
#if JSONCPP_CXX_STD_11
Value& operator=(Value&& other);
#endif
/// Swap everything.
void swap(Value& other);
@@ -384,9 +398,6 @@ public:
* \return false if !string. (Seg-fault if str or end are NULL.)
*/
bool getString(char const** begin, char const** end) const;
#ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
#endif
Int asInt() const;
UInt asUInt() const;
#if defined(JSON_HAS_INT64)
@@ -413,8 +424,8 @@ public:
bool isObject() const;
/// The `as<T>` and `is<T>` member function templates and specializations.
template <typename T> T as() const = delete;
template <typename T> bool is() const = delete;
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
bool isConvertibleTo(ValueType other) const;
@@ -467,9 +478,15 @@ public:
///
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value);
#if JSONCPP_CXX_STD_11
Value& append(Value&& value);
#endif
/// \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.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
@@ -498,13 +515,6 @@ public:
* \endcode
*/
Value& operator[](const StaticString& key);
#ifdef JSON_USE_CPPTL
/// Access an object value by name, create a null member if it does not exist.
Value& operator[](const CppTL::ConstString& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const CppTL::ConstString& key) const;
#endif
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const char* key, const Value& defaultValue) const;
@@ -517,11 +527,6 @@ public:
/// \note deep copy
/// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const;
#ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
#endif
/// Most general and efficient version of isMember()const, get()const,
/// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@@ -567,10 +572,6 @@ public:
bool isMember(const String& key) const;
/// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const;
#ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
bool isMember(const CppTL::ConstString& key) const;
#endif
/// \brief Return a list of the member names.
///
@@ -579,22 +580,13 @@ public:
/// \post if type() was nullValue, it remains nullValue
Members getMemberNames() const;
//# ifdef JSON_USE_CPPTL
// EnumMemberNames enumMemberNames() const;
// EnumValues enumValues() const;
//# endif
/// \deprecated Always pass len.
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
void setComment(const char* comment, CommentPlacement placement) {
setComment(String(comment, strlen(comment)), placement);
}
void setComment(const char* comment, CommentPlacement placement);
/// Comments must be //... or /* ... */
void setComment(const char* comment, size_t len, CommentPlacement placement) {
setComment(String(comment, len), placement);
}
void setComment(const char* comment, size_t len, CommentPlacement placement);
/// Comments must be //... or /* ... */
void setComment(String comment, CommentPlacement placement);
void setComment(const String& comment, CommentPlacement placement);
bool hasComment(CommentPlacement placement) const;
/// Include delimiters and embedded newlines.
String getComment(CommentPlacement placement) const;
@@ -656,18 +648,15 @@ private:
class Comments {
public:
Comments() = default;
Comments() {}
Comments(const Comments& that);
Comments(Comments&& that);
Comments& operator=(const Comments& that);
Comments& operator=(Comments&& that);
bool has(CommentPlacement slot) const;
String get(CommentPlacement slot) const;
void set(CommentPlacement slot, String comment);
void set(CommentPlacement slot, String s);
private:
using Array = std::array<String, numberOfCommentPlacement>;
std::unique_ptr<Array> ptr_;
String ptr_[numberOfCommentPlacement];
};
Comments comments_;
@@ -706,11 +695,6 @@ template <> inline float Value::as<float>() const { return asFloat(); }
template <> inline const char* Value::as<const char*>() const {
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
* access a node.
@@ -727,8 +711,8 @@ public:
private:
enum Kind { kindNone = 0, kindIndex, kindKey };
String key_;
ArrayIndex index_{};
Kind kind_{kindNone};
ArrayIndex index_;
Kind kind_;
};
/** \brief Experimental and untested: represents a "path" to access a node.
@@ -833,13 +817,14 @@ protected:
private:
Value::ObjectValues::iterator current_;
// Indicates that iterator is for a null value.
bool isNull_{true};
bool isNull_;
public:
// For some reason, BORLAND needs these at the end, rather
// than earlier. No idea why.
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.
@@ -862,7 +847,8 @@ public:
private:
/*! \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:
SelfType& operator=(const ValueIteratorBase& other);
@@ -908,13 +894,14 @@ public:
typedef ValueIterator SelfType;
ValueIterator();
explicit ValueIterator(const ValueConstIterator& other);
JSONCPP_OP_EXPLICIT ValueIterator(const ValueConstIterator& other);
ValueIterator(const ValueIterator& other);
private:
/*! \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:
SelfType& operator=(const SelfType& other);
@@ -960,4 +947,4 @@ inline void swap(Value& a, Value& b) { a.swap(b); }
#pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_H_INCLUDED
#endif // JSON_H_INCLUDED

View File

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

View File

@@ -119,12 +119,12 @@ public:
Json::Value settings_;
StreamWriterBuilder();
~StreamWriterBuilder() override;
~StreamWriterBuilder() JSONCPP_OVERRIDE;
/**
* \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;
* otherwise, indicate bad settings via 'invalid'.
@@ -169,7 +169,7 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
: public Writer {
public:
FastWriter();
~FastWriter() override = default;
~FastWriter() JSONCPP_OVERRIDE {}
void enableYAMLCompatibility();
@@ -183,15 +183,15 @@ public:
void omitEndingLineFeed();
public: // overridden from Writer
String write(const Value& root) override;
String write(const Value& root) JSONCPP_OVERRIDE;
private:
void writeValue(const Value& value);
String document_;
bool yamlCompatibilityEnabled_{false};
bool dropNullPlaceholders_{false};
bool omitEndingLineFeed_{false};
bool yamlCompatibilityEnabled_;
bool dropNullPlaceholders_;
bool omitEndingLineFeed_;
};
#if defined(_MSC_VER)
#pragma warning(pop)
@@ -229,14 +229,14 @@ class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
StyledWriter : public Writer {
public:
StyledWriter();
~StyledWriter() override = default;
~StyledWriter() JSONCPP_OVERRIDE {}
public: // overridden from Writer
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
* \param root Value to serialize.
* \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:
void writeValue(const Value& value);
@@ -257,9 +257,9 @@ private:
ChildValues childValues_;
String document_;
String indentString_;
unsigned int rightMargin_{74};
unsigned int indentSize_{3};
bool addChildValues_{false};
unsigned int rightMargin_;
unsigned int indentSize_;
bool addChildValues_;
};
#if defined(_MSC_VER)
#pragma warning(pop)
@@ -301,7 +301,7 @@ public:
* \param indentation Each level will be indented by this amount extra.
*/
StyledStreamWriter(String indentation = "\t");
~StyledStreamWriter() = default;
~StyledStreamWriter() {}
public:
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
@@ -331,7 +331,7 @@ private:
ChildValues childValues_;
OStream* document_;
String indentString_;
unsigned int rightMargin_{74};
unsigned int rightMargin_;
String indentation_;
bool addChildValues_ : 1;
bool indented_ : 1;
@@ -348,7 +348,7 @@ String JSON_API valueToString(LargestInt value);
String JSON_API valueToString(LargestUInt value);
String JSON_API valueToString(
double value, unsigned int precision = Value::defaultRealPrecision,
PrecisionType precisionType = PrecisionType::significantDigits);
PrecisionType precisionType = significantDigits);
String JSON_API valueToString(bool value);
String JSON_API valueToQuotedString(const char* value);

View File

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

5
meson_options.txt Normal file
View File

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

View File

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

View File

@@ -24,7 +24,9 @@ struct Options {
Json::String path;
Json::Features features;
bool parseOnly;
using writeFuncType = Json::String (*)(Json::Value const&);
typedef Json::String (*writeFuncType)(Json::Value const&);
writeFuncType write;
};
@@ -58,10 +60,10 @@ static Json::String readInputTestFile(const char* path) {
return "";
fseek(file, 0, SEEK_END);
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);
char* buffer = new char[size + 1];
buffer[size] = 0;
char* buffer = new char[usize + 1];
buffer[usize] = 0;
Json::String text;
if (fread(buffer, 1, usize, file) == usize)
text = buffer;
@@ -111,7 +113,9 @@ static void printValueTree(FILE* fout, Json::Value& value,
Json::Value::Members members(value.getMemberNames());
std::sort(members.begin(), members.end());
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
for (auto name : members) {
for (Json::Value::Members::const_iterator it = members.begin();
it != members.end(); it++) {
const Json::String& name = *it;
printValueTree(fout, value[name], path + suffix + name);
}
} break;
@@ -138,7 +142,7 @@ static int parseAndSaveValueTree(const Json::String& input,
features.allowDroppedNullPlaceholders_;
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::CharReader* reader(builder.newCharReader());
Json::String errors;
const bool parsingSuccessful =
reader->parse(input.data(), input.data() + input.size(), root, &errors);
@@ -148,7 +152,7 @@ static int parseAndSaveValueTree(const Json::String& input,
<< errors << std::endl;
return 1;
}
delete reader;
// We may instead check the legacy implementation (to ensure it doesn't
// randomly get broken).
} else {

View File

@@ -1,13 +1,7 @@
if( CMAKE_COMPILER_IS_GNUCXX )
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
#-Werror=* was introduced -after- GCC 4.1.2
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
endif()
endif( CMAKE_COMPILER_IS_GNUCXX )
add_compile_options("-Werror=strict-aliasing")
endif()
include(CheckIncludeFileCXX)
include(CheckTypeSize)
@@ -35,15 +29,15 @@ endif()
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
message(WARNING "Locale functionality is not supported")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
else()
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
endif()
endif()
set( JSONCPP_INCLUDE_DIR ../../include )
set(JSONCPP_INCLUDE_DIR ../../include)
set( PUBLIC_HEADERS
set(PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/config.h
${JSONCPP_INCLUDE_DIR}/json/forwards.h
${JSONCPP_INCLUDE_DIR}/json/json_features.h
@@ -52,48 +46,51 @@ set( PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/version.h
${JSONCPP_INCLUDE_DIR}/json/writer.h
${JSONCPP_INCLUDE_DIR}/json/assertions.h
)
)
source_group( "Public API" FILES ${PUBLIC_HEADERS} )
source_group("Public API" FILES ${PUBLIC_HEADERS})
set(jsoncpp_sources
json_tool.h
json_reader.cpp
json_valueiterator.inl
json_value.cpp
json_writer.cpp)
json_tool.h
json_reader.cpp
json_valueiterator.inl
json_value.cpp
json_writer.cpp
)
# Install instructions for this target
if(JSONCPP_WITH_CMAKE_PACKAGE)
set(INSTALL_EXPORT EXPORT jsoncpp)
else(JSONCPP_WITH_CMAKE_PACKAGE)
else()
set(INSTALL_EXPORT)
endif()
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL_BUILD )
add_compile_definitions(JSON_DLL_BUILD)
else()
add_definitions( -DJSON_DLL_BUILD )
add_definitions(-DJSON_DLL_BUILD)
endif()
endif()
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
set_target_properties( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
set_target_properties( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
set_target_properties( jsoncpp_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties( jsoncpp_lib PROPERTIES
OUTPUT_NAME jsoncpp
VERSION ${JSONCPP_VERSION}
SOVERSION ${JSONCPP_SOVERSION}
POSITION_INDEPENDENT_CODE ON
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
set_target_properties(jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
# Specify compiler features required when compiling a given target.
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
# for complete list of features available
if(CMAKE_CXX_STANDARD EQUAL "11")
target_compile_features(jsoncpp_lib PUBLIC
cxx_std_11 # Compiler mode is aware of C++ 11.
#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_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}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
install(TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories( jsoncpp_lib PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>)
target_include_directories(jsoncpp_lib PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()

View File

@@ -51,18 +51,15 @@ static size_t const stackLimit_g =
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using CharReaderPtr = std::unique_ptr<CharReader>;
#else
typedef std::auto_ptr<CharReader> CharReaderPtr;
#endif
typedef CharReader* CharReaderPtr;
// Implementation of class Features
// ////////////////////////////////
Features::Features() = default;
Features Features::all() { return {}; }
Features::Features()
: allowComments_(true), strictRoot_(false),
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
Features Features::all() { return Features(); }
Features Features::strictMode() {
Features features;
@@ -86,9 +83,15 @@ bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
// 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 collectComments) {
@@ -121,8 +124,8 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
end_ = endDoc;
collectComments_ = collectComments;
current_ = begin_;
lastValueEnd_ = nullptr;
lastValue_ = nullptr;
lastValueEnd_ = JSONCPP_NULL;
lastValue_ = JSONCPP_NULL;
commentsBefore_.clear();
errors_.clear();
while (!nodes_.empty())
@@ -376,7 +379,7 @@ void Reader::addComment(Location begin, Location end,
assert(collectComments_);
const String& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
assert(lastValue_ != nullptr);
assert(lastValue_ != JSONCPP_NULL);
lastValue_->setComment(normalized, placement);
} else {
commentsBefore_ += normalized;
@@ -464,7 +467,7 @@ bool Reader::readObject(Token& token) {
Value numberName;
if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd);
name = String(numberName.asCString());
name = numberName.asString();
} else {
break;
}
@@ -565,7 +568,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
Char c = *current++;
if (c < '0' || c > '9')
return decodeDouble(token, decoded);
auto digit(static_cast<Value::UInt>(c - '0'));
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, b) this is the last digit, and
@@ -629,7 +632,7 @@ bool Reader::decodeString(Token& token, String& decoded) {
Char c = *current++;
if (c == '"')
break;
else if (c == '\\') {
if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@@ -798,7 +801,9 @@ String Reader::getFormatedErrorMessages() const {
String Reader::getFormattedErrorMessages() const {
String formattedMessage;
for (const auto& error : errors_) {
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
@@ -811,7 +816,9 @@ String Reader::getFormattedErrorMessages() const {
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
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;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
@@ -832,7 +839,7 @@ bool Reader::pushError(const Value& value, const String& message) {
ErrorInfo info;
info.token_ = token;
info.message_ = message;
info.extra_ = nullptr;
info.extra_ = JSONCPP_NULL;
errors_.push_back(info);
return true;
}
@@ -863,6 +870,7 @@ class OurFeatures {
public:
static OurFeatures all();
bool allowComments_;
bool allowTrailingCommas_;
bool strictRoot_;
bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_;
@@ -870,10 +878,11 @@ public:
bool failIfExtra_;
bool rejectDupKeys_;
bool allowSpecialFloats_;
bool skipBom_;
size_t stackLimit_;
}; // OurFeatures
OurFeatures OurFeatures::all() { return {}; }
OurFeatures OurFeatures::all() { return OurFeatures(); }
// Implementation of class Reader
// ////////////////////////////////
@@ -882,15 +891,15 @@ OurFeatures OurFeatures::all() { return {}; }
// for implementing JSON reading.
class OurReader {
public:
using Char = char;
using Location = const Char*;
typedef char Char;
typedef const Char* Location;
struct StructuredError {
ptrdiff_t offset_start;
ptrdiff_t offset_limit;
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 collectComments = true);
String getFormattedErrorMessages() const;
@@ -934,10 +943,11 @@ private:
Location extra_;
};
using Errors = std::deque<ErrorInfo>;
typedef std::deque<ErrorInfo> Errors;
bool readToken(Token& token);
void skipSpaces();
void skipBom(bool skipBom);
bool match(const Char* pattern, int patternLength);
bool readComment();
bool readCStyleComment(bool* containsNewLineResult);
@@ -958,7 +968,8 @@ private:
unsigned int& unicode);
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
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 addErrorAndRecover(const String& message, Token& token,
TokenType skipUntilToken);
@@ -974,21 +985,21 @@ private:
static String normalizeEOL(Location begin, Location end);
static bool containsNewLine(Location begin, Location end);
using Nodes = std::stack<Value*>;
typedef std::stack<Value*> Nodes;
Nodes nodes_{};
Errors errors_{};
String document_{};
Location begin_ = nullptr;
Location end_ = nullptr;
Location current_ = nullptr;
Location lastValueEnd_ = nullptr;
Value* lastValue_ = nullptr;
bool lastValueHasAComment_ = false;
String commentsBefore_{};
Nodes nodes_;
Errors errors_;
String document_;
Location begin_;
Location end_;
Location current_;
Location lastValueEnd_;
Value* lastValue_;
bool lastValueHasAComment_;
String commentsBefore_;
OurFeatures const features_;
bool collectComments_ = false;
bool collectComments_;
}; // OurReader
// complete copy of Read impl, for OurReader
@@ -1001,7 +1012,11 @@ bool OurReader::containsNewLine(OurReader::Location begin,
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 collectComments) {
@@ -1013,14 +1028,16 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
end_ = endDoc;
collectComments_ = collectComments;
current_ = begin_;
lastValueEnd_ = nullptr;
lastValue_ = nullptr;
lastValueEnd_ = JSONCPP_NULL;
lastValue_ = JSONCPP_NULL;
commentsBefore_.clear();
errors_.clear();
while (!nodes_.empty())
nodes_.pop();
nodes_.push(&root);
// skip byte order mark if it exists at the beginning of the UTF-8 text.
skipBom(features_.skipBom_);
bool successful = readValue();
nodes_.pop();
Token token;
@@ -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) {
if (end_ - current_ < patternLength)
return false;
@@ -1337,7 +1364,7 @@ void OurReader::addComment(Location begin, Location end,
assert(collectComments_);
const String& normalized = normalizeEOL(begin, end);
if (placement == commentAfterOnSameLine) {
assert(lastValue_ != nullptr);
assert(lastValue_ != JSONCPP_NULL);
lastValue_->setComment(normalized, placement);
} else {
commentsBefore_ += normalized;
@@ -1349,11 +1376,10 @@ bool OurReader::readCStyleComment(bool* containsNewLineResult) {
while ((current_ + 1) < end_) {
Char c = getNextChar();
if (c == '*' && *current_ == '/') {
if (c == '*' && *current_ == '/')
break;
} else if (c == '\n') {
if (c == '\n')
*containsNewLineResult = true;
}
}
return getNextChar() == '/';
@@ -1437,7 +1463,9 @@ bool OurReader::readObject(Token& token) {
initialTokenOk = readToken(tokenName);
if (!initialTokenOk)
break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
if (tokenName.type_ == tokenObjectEnd &&
(name.empty() ||
features_.allowTrailingCommas_)) // empty object or trailing comma
return true;
name.clear();
if (tokenName.type_ == tokenString) {
@@ -1491,15 +1519,19 @@ bool OurReader::readArray(Token& token) {
Value init(arrayValue);
currentValue().swapPayload(init);
currentValue().setOffsetStart(token.start_ - begin_);
skipSpaces();
if (current_ != end_ && *current_ == ']') // empty array
{
Token endArray;
readToken(endArray);
return true;
}
int index = 0;
for (;;) {
skipSpaces();
if (current_ != end_ && *current_ == ']' &&
(index == 0 ||
(features_.allowTrailingCommas_ &&
!features_.allowDroppedNullPlaceholders_))) // empty array or trailing
// comma
{
Token endArray;
readToken(endArray);
return true;
}
Value& value = currentValue()[index++];
nodes_.push(&value);
bool ok = readValue();
@@ -1548,32 +1580,36 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
// 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
// into an unsigned integer.
static_assert(Value::maxLargestInt <= Value::maxLargestUInt,
"Int must be smaller than UInt");
JSONCPP_STATIC_ASSERT(LargestUInt(Value::maxLargestInt) <=
Value::maxLargestUInt,
"Int must be smaller than Uint");
// We need to convert minLargestInt into a positive number. The easiest way
// to do this conversion is to assume our "threshold" value of minLargestInt
// divided by 10 can fit in maxLargestInt when absolute valued. This should
// be a safe assumption.
static_assert(Value::minLargestInt <= -Value::maxLargestInt,
"The absolute value of minLargestInt must be greater than or "
"equal to maxLargestInt");
static_assert(Value::minLargestInt / 10 >= -Value::maxLargestInt,
"The absolute value of minLargestInt must be only 1 magnitude "
"larger than maxLargest Int");
JSONCPP_STATIC_ASSERT(
Value::minLargestInt <= -Value::maxLargestInt,
"The absolute value of minLargestInt must ve greater than or"
"equal to maxLargestInt");
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;
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
// -Value::minLargestInt will cause an overflow, we first divide by 10 and
// then take the inverse. This assumes that minLargestInt is only a single
// power of 10 different in magnitude, which we check above. For the last
// digit, we take the modulus before negating for the same reason.
static constexpr Value::LargestUInt negative_threshold =
static JSONCPP_CONST Value::LargestUInt negative_threshold =
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));
const Value::LargestUInt threshold =
@@ -1654,9 +1690,9 @@ bool OurReader::decodeString(Token& token, String& decoded) {
Location end = token.end_ - 1; // do not include '"'
while (current != end) {
Char c = *current++;
if (c == '"') {
if (c == '"')
break;
} else if (c == '\\') {
if (c == '\\') {
if (current == end)
return addError("Empty escape sequence in string", token, current);
Char escape = *current++;
@@ -1820,7 +1856,9 @@ String OurReader::getLocationLineAndColumn(Location location) const {
String OurReader::getFormattedErrorMessages() const {
String formattedMessage;
for (const auto& error : errors_) {
for (Errors::const_iterator itError = errors_.begin();
itError != errors_.end(); ++itError) {
const ErrorInfo& error = *itError;
formattedMessage +=
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
formattedMessage += " " + error.message_ + "\n";
@@ -1833,7 +1871,9 @@ String OurReader::getFormattedErrorMessages() const {
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
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;
structured.offset_start = error.token_.start_ - begin_;
structured.offset_limit = error.token_.end_ - begin_;
@@ -1851,7 +1891,7 @@ public:
OurCharReader(bool collectComments, OurFeatures const& features)
: collectComments_(collectComments), reader_(features) {}
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_);
if (errs) {
*errs = reader_.getFormattedErrorMessages();
@@ -1861,11 +1901,12 @@ public:
};
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
CharReaderBuilder::~CharReaderBuilder() = default;
CharReaderBuilder::~CharReaderBuilder() {}
CharReader* CharReaderBuilder::newCharReader() const {
bool collectComments = settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all();
features.allowComments_ = settings_["allowComments"].asBool();
features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
features.strictRoot_ = settings_["strictRoot"].asBool();
features.allowDroppedNullPlaceholders_ =
settings_["allowDroppedNullPlaceholders"].asBool();
@@ -1878,12 +1919,14 @@ CharReader* CharReaderBuilder::newCharReader() const {
features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
features.skipBom_ = settings_["skipBom"].asBool();
return new OurCharReader(collectComments, features);
}
static void getValidReaderKeys(std::set<String>* valid_keys) {
valid_keys->clear();
valid_keys->insert("collectComments");
valid_keys->insert("allowComments");
valid_keys->insert("allowTrailingCommas");
valid_keys->insert("strictRoot");
valid_keys->insert("allowDroppedNullPlaceholders");
valid_keys->insert("allowNumericKeys");
@@ -1892,6 +1935,7 @@ static void getValidReaderKeys(std::set<String>* valid_keys) {
valid_keys->insert("failIfExtra");
valid_keys->insert("rejectDupKeys");
valid_keys->insert("allowSpecialFloats");
valid_keys->insert("skipBom");
}
bool CharReaderBuilder::validate(Json::Value* invalid) const {
Json::Value my_invalid;
@@ -1917,6 +1961,7 @@ Value& CharReaderBuilder::operator[](const String& key) {
void CharReaderBuilder::strictMode(Json::Value* settings) {
//! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false;
(*settings)["allowTrailingCommas"] = false;
(*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@@ -1925,6 +1970,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
(*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderStrictMode]
}
// static
@@ -1932,6 +1978,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
//! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true;
(*settings)["allowComments"] = true;
(*settings)["allowTrailingCommas"] = true;
(*settings)["strictRoot"] = false;
(*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false;
@@ -1940,6 +1987,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
(*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderDefaults]
}
@@ -1955,7 +2003,9 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
char const* end = begin + doc.size();
// Note that we do not actually need a null-terminator.
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) {

View File

@@ -8,16 +8,14 @@
#include <json/value.h>
#include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert>
#include <cmath>
#include <cstddef>
#include <cstring>
#include <iostream>
#include <sstream>
#include <utility>
#ifdef JSON_USE_CPPTL
#include <cpptl/conststring.h>
#endif
#include <algorithm> // min()
#include <cstddef> // size_t
// Provide implementation equivalent of std::snprintf for older _MSC compilers
#if defined(_MSC_VER) && _MSC_VER < 1900
@@ -50,14 +48,6 @@ int JSON_API msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
#define JSON_ASSERT_UNREACHABLE assert(false)
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.
// 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;
char* newString = static_cast<char*>(malloc(length + 1));
if (newString == nullptr) {
if (newString == JSONCPP_NULL) {
throwRuntimeError("in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer");
}
@@ -140,9 +130,9 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing");
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
size_t actualLength = sizeof(length) + length + 1;
char* newString = static_cast<char*>(malloc(actualLength));
if (newString == nullptr) {
if (newString == JSONCPP_NULL) {
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer");
}
@@ -202,8 +192,8 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); }
namespace Json {
#if JSON_USE_EXCEPTION
Exception::Exception(String msg) : msg_(std::move(msg)) {}
Exception::~Exception() JSONCPP_NOEXCEPT = default;
Exception::Exception(String msg) : msg_(JSONCPP_MOVE(msg)) {}
Exception::~Exception() JSONCPP_NOEXCEPT {}
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
RuntimeError::RuntimeError(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);
}
#else // !JSON_USE_EXCEPTION
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { abort(); }
JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
JSONCPP_NORETURN void throwLogicError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
#endif
// //////////////////////////////////////////////////////////////////
@@ -229,7 +225,8 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
// Notes: policy_ indicates if the string was allocated when
// 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,
DuplicationPolicy allocate)
@@ -240,9 +237,10 @@ Value::CZString::CZString(char const* str, unsigned length,
}
Value::CZString::CZString(const CZString& other) {
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
? duplicateStringValue(other.cstr_, other.storage_.length_)
: other.cstr_);
cstr_ =
(other.storage_.policy_ != noDuplication && other.cstr_ != JSONCPP_NULL
? duplicateStringValue(other.cstr_, other.storage_.length_)
: other.cstr_);
storage_.policy_ =
static_cast<unsigned>(
other.cstr_
@@ -254,12 +252,12 @@ Value::CZString::CZString(const CZString& other) {
3U;
storage_.length_ = other.storage_.length_;
}
#if JSONCPP_CXX_STD_11
Value::CZString::CZString(CZString&& other)
: cstr_(other.cstr_), index_(other.index_) {
other.cstr_ = nullptr;
other.cstr_ = JSONCPP_NULL;
}
#endif
Value::CZString::~CZString() {
if (cstr_ && storage_.policy_ == duplicate) {
releaseStringValue(const_cast<char*>(cstr_),
@@ -280,14 +278,14 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
index_ = other.index_;
return *this;
}
#if JSONCPP_CXX_STD_11
Value::CZString& Value::CZString::operator=(CZString&& other) {
cstr_ = other.cstr_;
index_ = other.index_;
other.cstr_ = nullptr;
other.cstr_ = JSONCPP_NULL;
return *this;
}
#endif
bool Value::CZString::operator<(const CZString& other) const {
if (!cstr_)
return index_ < other.index_;
@@ -396,7 +394,7 @@ Value::Value(double value) {
Value::Value(const char* value) {
initBasic(stringValue, true);
JSON_ASSERT_MESSAGE(value != nullptr,
JSON_ASSERT_MESSAGE(value != JSONCPP_NULL,
"Null Value Passed to Value Constructor");
value_.string_ = duplicateAndPrefixStringValue(
value, static_cast<unsigned>(strlen(value)));
@@ -419,14 +417,6 @@ Value::Value(const StaticString& value) {
value_.string_ = const_cast<char*>(value.c_str());
}
#ifdef JSON_USE_CPPTL
Value::Value(const CppTL::ConstString& value) {
initBasic(stringValue, true);
value_.string_ = duplicateAndPrefixStringValue(
value, static_cast<unsigned>(value.length()));
}
#endif
Value::Value(bool value) {
initBasic(booleanValue);
value_.bool_ = value;
@@ -436,11 +426,12 @@ Value::Value(const Value& other) {
dupPayload(other);
dupMeta(other);
}
#if JSONCPP_CXX_STD_11
Value::Value(Value&& other) {
initBasic(nullValue);
swap(other);
}
#endif
Value::~Value() {
releasePayload();
@@ -451,11 +442,12 @@ Value& Value::operator=(const Value& other) {
Value(other).swap(*this);
return *this;
}
#if JSONCPP_CXX_STD_11
Value& Value::operator=(Value&& other) {
other.swap(*this);
return *this;
}
#endif
void Value::swapPayload(Value& other) {
std::swap(bits_, other.bits_);
@@ -507,8 +499,9 @@ bool Value::operator<(const Value& other) const {
case booleanValue:
return value_.bool_ < other.value_.bool_;
case stringValue: {
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
return other.value_.string_ != nullptr;
if ((value_.string_ == JSONCPP_NULL) ||
(other.value_.string_ == JSONCPP_NULL)) {
return other.value_.string_ != JSONCPP_NULL;
}
unsigned this_len;
unsigned other_len;
@@ -529,9 +522,10 @@ bool Value::operator<(const Value& other) const {
}
case arrayValue:
case objectValue: {
int delta = int(value_.map_->size() - other.value_.map_->size());
if (delta)
return delta < 0;
long unsigned int thisSize = value_.map_->size();
long unsigned int otherSize = other.value_.map_->size();
if (thisSize != otherSize)
return thisSize < otherSize;
return (*value_.map_) < (*other.value_.map_);
}
default:
@@ -561,7 +555,8 @@ bool Value::operator==(const Value& other) const {
case booleanValue:
return value_.bool_ == other.value_.bool_;
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_);
}
unsigned this_len;
@@ -593,8 +588,8 @@ bool Value::operator!=(const Value& other) const { return !(*this == other); }
const char* Value::asCString() const {
JSON_ASSERT_MESSAGE(type() == stringValue,
"in Json::Value::asCString(): requires stringValue");
if (value_.string_ == nullptr)
return nullptr;
if (value_.string_ == JSONCPP_NULL)
return JSONCPP_NULL;
unsigned this_len;
char const* this_str;
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 {
if (type() != stringValue)
return false;
if (value_.string_ == nullptr)
if (value_.string_ == JSONCPP_NULL)
return false;
unsigned length;
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
@@ -633,7 +628,7 @@ String Value::asString() const {
case nullValue:
return "";
case stringValue: {
if (value_.string_ == nullptr)
if (value_.string_ == JSONCPP_NULL)
return "";
unsigned this_len;
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 {
switch (type()) {
case intValue:
@@ -825,7 +811,7 @@ bool Value::asBool() const {
return value_.uint_ != 0;
case realValue: {
// 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;
}
default:
@@ -894,8 +880,7 @@ ArrayIndex Value::size() const {
bool Value::empty() const {
if (isNull() || isArray() || isObject())
return size() == 0U;
else
return false;
return false;
}
Value::operator bool() const { return !isNull(); }
@@ -941,7 +926,7 @@ Value& Value::operator[](ArrayIndex index) {
if (type() == nullValue)
*this = Value(arrayValue);
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)
return (*it).second;
@@ -980,7 +965,7 @@ const Value& Value::operator[](int index) const {
void Value::initBasic(ValueType type, bool allocated) {
setType(type);
setIsAllocated(allocated);
comments_ = Comments{};
comments_ = Comments();
start_ = 0;
limit_ = 0;
}
@@ -1055,7 +1040,7 @@ Value& Value::resolveReference(const char* key) {
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
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)
return (*it).second;
@@ -1074,7 +1059,7 @@ Value& Value::resolveReference(char const* key, char const* end) {
*this = Value(objectValue);
CZString actualKey(key, static_cast<unsigned>(end - key),
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)
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 "
"objectValue or nullValue");
if (type() == nullValue)
return nullptr;
return JSONCPP_NULL;
CZString actualKey(begin, static_cast<unsigned>(end - begin),
CZString::noDuplication);
ObjectValues::const_iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return nullptr;
return JSONCPP_NULL;
return &(*it).second;
}
Value* Value::demand(char const* begin, char const* end) {
@@ -1135,20 +1120,8 @@ Value& Value::operator[](const StaticString& key) {
return resolveReference(key.c_str());
}
#ifdef JSON_USE_CPPTL
Value& Value::operator[](const CppTL::ConstString& key) {
return resolveReference(key.c_str(), key.end_c_str());
}
Value const& Value::operator[](CppTL::ConstString const& key) const {
Value const* found = find(key.c_str(), key.end_c_str());
if (!found)
return nullSingleton();
return *found;
}
#endif
#if JSONCPP_CXX_STD_11
Value& Value::append(const Value& value) { return append(Value(value)); }
Value& Value::append(Value&& value) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == 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;
}
#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,
"in Json::Value::insert: requires arrayValue");
ArrayIndex length = size();
if (index > length) {
return false;
} else {
for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = std::move((*this)[i - 1]);
}
(*this)[index] = std::move(newValue);
return true;
}
for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = JSONCPP_MOVE((*this)[i - 1]);
}
(*this)[index] = JSONCPP_MOVE(newValue);
return true;
}
Value Value::get(char const* begin, char const* end,
Value const& defaultValue) const {
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::noDuplication);
auto it = value_.map_->find(actualKey);
ObjectValues::iterator it = value_.map_->find(actualKey);
if (it == value_.map_->end())
return false;
if (removed)
*removed = std::move(it->second);
*removed = JSONCPP_MOVE(it->second);
value_.map_->erase(it);
return true;
}
@@ -1221,7 +1203,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
return false;
}
CZString key(index);
auto it = value_.map_->find(key);
ObjectValues::iterator it = value_.map_->find(key);
if (it == value_.map_->end()) {
return false;
}
@@ -1235,21 +1217,14 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
}
// erase the last one ("leftover")
CZString keyLast(oldSize - 1);
auto itLast = value_.map_->find(keyLast);
ObjectValues::iterator itLast = value_.map_->find(keyLast);
value_.map_->erase(itLast);
return true;
}
#ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key,
const Value& defaultValue) const {
return get(key.c_str(), key.end_c_str(), defaultValue);
}
#endif
bool Value::isMember(char const* begin, char const* end) const {
Value const* value = find(begin, end);
return nullptr != value;
return JSONCPP_NULL != value;
}
bool Value::isMember(char const* key) const {
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());
}
#ifdef JSON_USE_CPPTL
bool Value::isMember(const CppTL::ConstString& key) const {
return isMember(key.c_str(), key.end_c_str());
}
#endif
Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue,
@@ -1279,31 +1248,6 @@ Value::Members Value::getMemberNames() const {
}
return members;
}
//
//# ifdef JSON_USE_CPPTL
// EnumMemberNames
// Value::enumMemberNames() const
//{
// if ( type() == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
// MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
//
//
// EnumValues
// Value::enumValues() const
//{
// if ( type() == objectValue || type() == arrayValue )
// return CppTL::Enum::anyValues( *(value_.map_),
// CppTL::Type<const Value &>() );
// return EnumValues();
//}
//
//# endif
static bool IsIntegral(double d) {
double integral_part;
@@ -1430,53 +1374,44 @@ bool Value::isArray() const { return type() == arrayValue; }
bool Value::isObject() const { return type() == objectValue; }
Value::Comments::Comments(const Comments& that)
: ptr_{cloneUnique(that.ptr_)} {}
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
Value::Comments::Comments(const Comments& that) {
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
ptr_[i] = that.ptr_[i];
}
}
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;
}
Value::Comments& Value::Comments::operator=(Comments&& that) {
ptr_ = std::move(that.ptr_);
return *this;
}
bool Value::Comments::has(CommentPlacement slot) const {
return ptr_ && !(*ptr_)[slot].empty();
return !ptr_[slot].empty();
}
String Value::Comments::get(CommentPlacement slot) const {
if (!ptr_)
return {};
return (*ptr_)[slot];
}
String Value::Comments::get(CommentPlacement slot) const { return ptr_[slot]; }
void Value::Comments::set(CommentPlacement slot, String comment) {
if (!ptr_) {
ptr_ = std::unique_ptr<Array>(new Array());
}
// check comments array boundry.
if (slot < CommentPlacement::numberOfCommentPlacement) {
(*ptr_)[slot] = std::move(comment);
if (slot < numberOfCommentPlacement) {
ptr_[slot] = comment;
}
}
void Value::setComment(String comment, CommentPlacement placement) {
if (!comment.empty() && (comment.back() == '\n')) {
void Value::setComment(const char* comment, CommentPlacement placement) {
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.
comment.pop_back();
len -= 1;
}
JSON_ASSERT(!comment.empty());
JSON_ASSERT_MESSAGE(
comment[0] == '\0' || comment[0] == '/',
"in Json::Value::setComment(): Comments must start with /");
comments_.set(placement, std::move(comment));
comments_.set(placement, String(comment, len));
}
void Value::setComment(const String& comment, CommentPlacement placement) {
setComment(comment.c_str(), comment.length(), placement);
}
bool Value::hasComment(CommentPlacement placement) const {
return comments_.has(placement);
}
@@ -1513,7 +1448,7 @@ Value::const_iterator Value::begin() const {
default:
break;
}
return {};
return const_iterator();
}
Value::const_iterator Value::end() const {
@@ -1526,7 +1461,7 @@ Value::const_iterator Value::end() const {
default:
break;
}
return {};
return const_iterator();
}
Value::iterator Value::begin() {
@@ -1558,14 +1493,15 @@ Value::iterator Value::end() {
// class PathArgument
// //////////////////////////////////////////////////////////////////
PathArgument::PathArgument() = default;
PathArgument::PathArgument() {}
PathArgument::PathArgument(ArrayIndex index)
: index_(index), kind_(kindIndex) {}
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
// //////////////////////////////////////////////////////////////////
@@ -1586,7 +1522,7 @@ Path::Path(const String& path, const PathArgument& a1, const PathArgument& a2,
void Path::makePath(const String& path, const InArgs& in) {
const char* current = path.c_str();
const char* end = current + path.length();
auto itInArg = in.begin();
InArgs::const_iterator itInArg = in.begin();
while (current != end) {
if (*current == '[') {
++current;
@@ -1632,7 +1568,9 @@ void Path::invalidPath(const String& /*path*/, int /*location*/) {
const Value& Path::resolve(const Value& root) const {
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 (!node->isArray() || !node->isValidIndex(arg.index_)) {
// 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 {
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 (!node->isArray() || !node->isValidIndex(arg.index_))
return defaultValue;
@@ -1675,7 +1615,9 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
Value& Path::make(Value& 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 (!node->isArray()) {
// Error: node is not an array at position ...

View File

@@ -15,7 +15,7 @@ namespace Json {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueIteratorBase::ValueIteratorBase() : current_() {}
ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
ValueIteratorBase::ValueIteratorBase(
const Value::ObjectValues::iterator& current)
@@ -30,9 +30,6 @@ void ValueIteratorBase::decrement() { --current_; }
ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance(const SelfType& other) const {
#ifdef JSON_USE_CPPTL_SMALLMAP
return other.current_ - current_;
#else
// Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance
@@ -53,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
++myDistance;
}
return myDistance;
#endif
}
bool ValueIteratorBase::isEqual(const SelfType& other) const {
@@ -102,8 +98,8 @@ char const* ValueIteratorBase::memberName() const {
char const* ValueIteratorBase::memberName(char const** end) const {
const char* cname = (*current_).first.data();
if (!cname) {
*end = nullptr;
return nullptr;
*end = JSONCPP_NULL;
return JSONCPP_NULL;
}
*end = cname + (*current_).first.length();
return cname;
@@ -117,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const {
// //////////////////////////////////////////////////////////////////
// //////////////////////////////////////////////////////////////////
ValueConstIterator::ValueConstIterator() = default;
ValueConstIterator::ValueConstIterator() {}
ValueConstIterator::ValueConstIterator(
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)
: ValueIteratorBase(current) {}
@@ -150,7 +146,8 @@ ValueIterator::ValueIterator(const ValueConstIterator& other)
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) {
copy(other);

View File

@@ -83,11 +83,7 @@
namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
#endif
typedef StreamWriter* StreamWriterPtr;
String valueToString(LargestInt value) {
UIntToStringBuffer buffer;
@@ -136,12 +132,12 @@ String valueToString(double value, bool useSpecialFloats,
String buffer(size_t(36), '\0');
while (true) {
int len = jsoncpp_snprintf(
&*buffer.begin(), buffer.size(),
(precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
precision, value);
int len =
jsoncpp_snprintf(&*buffer.begin(), buffer.size(),
(precisionType == significantDigits) ? "%.*g" : "%.*f",
precision, value);
assert(len >= 0);
auto wouldPrint = static_cast<size_t>(len);
size_t wouldPrint = static_cast<size_t>(len);
if (wouldPrint >= buffer.size()) {
buffer.resize(wouldPrint + 1);
continue;
@@ -153,7 +149,7 @@ String valueToString(double value, bool useSpecialFloats,
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
// strip the zero padding from the right
if (precisionType == PrecisionType::decimalPlaces) {
if (precisionType == decimalPlaces) {
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;
for (char const* cur = s; cur < end; ++cur) {
if (*cur == '\\' || *cur == '\"' || *cur < ' ' ||
static_cast<unsigned char>(*cur) < 0x80)
if (*cur == '\\' || *cur == '\"' ||
static_cast<unsigned char>(*cur) < ' ' ||
static_cast<unsigned char>(*cur) >= 0x80)
return true;
}
return false;
@@ -266,7 +263,7 @@ static String toHex16Bit(unsigned int x) {
static String valueToQuotedStringN(const char* value, unsigned length,
bool emitUTF8 = false) {
if (value == nullptr)
if (value == JSONCPP_NULL)
return "";
if (!isAnyCharRequiredQuoting(value, length))
@@ -350,14 +347,14 @@ String valueToQuotedString(const char* value) {
// Class Writer
// //////////////////////////////////////////////////////////////////
Writer::~Writer() = default;
Writer::~Writer() {}
// Class FastWriter
// //////////////////////////////////////////////////////////////////
FastWriter::FastWriter()
= default;
: yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
omitEndingLineFeed_(false) {}
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
@@ -413,7 +410,8 @@ void FastWriter::writeValue(const Value& value) {
case objectValue: {
Value::Members members(value.getMemberNames());
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;
if (it != members.begin())
document_ += ',';
@@ -430,7 +428,8 @@ void FastWriter::writeValue(const Value& value) {
// Class StyledWriter
// //////////////////////////////////////////////////////////////////
StyledWriter::StyledWriter() = default;
StyledWriter::StyledWriter()
: rightMargin_(74), indentSize_(3), addChildValues_() {}
String StyledWriter::write(const Value& root) {
document_.clear();
@@ -481,7 +480,7 @@ void StyledWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
auto it = members.begin();
Value::Members::const_iterator it = members.begin();
for (;;) {
const String& name = *it;
const Value& childValue = value[name];
@@ -643,8 +642,9 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
// //////////////////////////////////////////////////////////////////
StyledStreamWriter::StyledStreamWriter(String indentation)
: document_(nullptr), indentation_(std::move(indentation)),
addChildValues_(), indented_(false) {}
: document_(JSONCPP_NULL), rightMargin_(74),
indentation_(JSONCPP_MOVE(indentation)), addChildValues_(),
indented_(false) {}
void StyledStreamWriter::write(OStream& out, const Value& root) {
document_ = &out;
@@ -658,7 +658,7 @@ void StyledStreamWriter::write(OStream& out, const Value& root) {
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*document_ << "\n";
document_ = nullptr; // Forget the stream, for safety.
document_ = JSONCPP_NULL; // Forget the stream, for safety.
}
void StyledStreamWriter::writeValue(const Value& value) {
@@ -699,7 +699,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
else {
writeWithIndent("{");
indent();
auto it = members.begin();
Value::Members::const_iterator it = members.begin();
for (;;) {
const String& name = *it;
const Value& childValue = value[name];
@@ -877,7 +877,7 @@ struct BuiltStyledStreamWriter : public StreamWriter {
String endingLineFeedSymbol, bool useSpecialFloats,
bool emitUTF8, unsigned int precision,
PrecisionType precisionType);
int write(Value const& root, OStream* sout) override;
int write(Value const& root, OStream* sout) JSONCPP_OVERRIDE;
private:
void writeValue(Value const& value);
@@ -892,7 +892,7 @@ private:
void writeCommentAfterValueOnSameLine(Value const& root);
static bool hasCommentForValue(const Value& value);
using ChildValues = std::vector<String>;
typedef std::vector<String> ChildValues;
ChildValues childValues_;
String indentString_;
@@ -913,9 +913,10 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
String indentation, CommentStyle::Enum cs, String colonSymbol,
String nullSymbol, String endingLineFeedSymbol, bool useSpecialFloats,
bool emitUTF8, unsigned int precision, PrecisionType precisionType)
: rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
: rightMargin_(74), indentation_(JSONCPP_MOVE(indentation)), cs_(cs),
colonSymbol_(JSONCPP_MOVE(colonSymbol)),
nullSymbol_(JSONCPP_MOVE(nullSymbol)),
endingLineFeedSymbol_(JSONCPP_MOVE(endingLineFeedSymbol)),
addChildValues_(false), indented_(false),
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
precision_(precision), precisionType_(precisionType) {}
@@ -931,7 +932,7 @@ int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
writeValue(root);
writeCommentAfterValueOnSameLine(root);
*sout_ << endingLineFeedSymbol_;
sout_ = nullptr;
sout_ = JSONCPP_NULL;
return 0;
}
void BuiltStyledStreamWriter::writeValue(Value const& value) {
@@ -974,7 +975,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
else {
writeWithIndent("{");
indent();
auto it = members.begin();
Value::Members::const_iterator it = members.begin();
for (;;) {
String const& name = *it;
Value const& childValue = value[name];
@@ -1150,11 +1151,11 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
///////////////
// StreamWriter
StreamWriter::StreamWriter() : sout_(nullptr) {}
StreamWriter::~StreamWriter() = default;
StreamWriter::Factory::~Factory() = default;
StreamWriter::StreamWriter() : sout_(JSONCPP_NULL) {}
StreamWriter::~StreamWriter() {}
StreamWriter::Factory::~Factory() {}
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
StreamWriterBuilder::~StreamWriterBuilder() = default;
StreamWriterBuilder::~StreamWriterBuilder() {}
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
const String indentation = settings_["indentation"].asString();
const String cs_str = settings_["commentStyle"].asString();
@@ -1174,9 +1175,9 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
}
PrecisionType precisionType(significantDigits);
if (pt_str == "significant") {
precisionType = PrecisionType::significantDigits;
precisionType = significantDigits;
} else if (pt_str == "decimal") {
precisionType = PrecisionType::decimalPlaces;
precisionType = decimalPlaces;
} else {
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
}
@@ -1246,6 +1247,7 @@ String writeString(StreamWriter::Factory const& factory, Value const& root) {
OStringStream sout;
StreamWriterPtr const writer(factory.newStreamWriter());
writer->write(root, &sout);
delete writer;
return sout.str();
}
@@ -1253,6 +1255,7 @@ OStream& operator<<(OStream& sout, Value const& root) {
StreamWriterBuilder builder;
StreamWriterPtr const writer(builder.newStreamWriter());
writer->write(root, &sout);
delete writer;
return sout;
}

View File

@@ -1,46 +1,37 @@
# vim: et ts=4 sts=4 sw=4 tw=0
add_executable( jsoncpp_test
jsontest.cpp
jsontest.h
fuzz.cpp
fuzz.h
main.cpp
)
add_executable(jsoncpp_test
jsontest.cpp
jsontest.h
fuzz.cpp
fuzz.h
main.cpp
)
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions( -DJSON_DLL )
endif()
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL )
else()
add_definitions( -DJSON_DLL )
endif()
endif()
target_link_libraries(jsoncpp_test jsoncpp_lib)
# another way to solve issue #90
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
add_test(NAME jsoncpp_test
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
)
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
# Run unit tests in post-build
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
if(BUILD_SHARED_LIBS)
# First, copy the shared lib, for Microsoft.
# Then, run the test executable.
add_custom_command( TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:jsoncpp_lib> $<TARGET_FILE_DIR:jsoncpp_test>
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
else(BUILD_SHARED_LIBS)
# Just run the test executable.
add_custom_command( TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
endif()
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
add_test(NAME jsoncpp_test
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
add_custom_command(TARGET jsoncpp_test
POST_BUILD
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
)
endif()
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)

View File

@@ -5,11 +5,9 @@
#include "fuzz.h"
#include <cstdint>
#include <json/config.h>
#include <json/json.h>
#include <memory>
#include <stdint.h>
#include <string>
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_["allowSpecialFloats_"] = hash_settings & (1 << 8);
builder.settings_["collectComments"] = hash_settings & (1 << 9);
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::CharReader* reader(builder.newCharReader());
Json::Value root;
const char* data_str = reinterpret_cast<const char*>(data);
try {
reader->parse(data_str, data_str + size, &root, nullptr);
reader->parse(data_str, data_str + size, &root, JSONCPP_NULL);
} catch (Json::Exception const&) {
}
delete reader;
// Whether it succeeded or not doesn't matter.
return 0;
}

View File

@@ -73,10 +73,11 @@ namespace JsonTest {
// class TestResult
// //////////////////////////////////////////////////////////////////
TestResult::TestResult() {
TestResult::TestResult()
: predicateId_(1), lastUsedPredicateId_(0), messageTarget_(JSONCPP_NULL) {
// The root predicate has id 0
rootPredicateNode_.id_ = 0;
rootPredicateNode_.next_ = nullptr;
rootPredicateNode_.next_ = JSONCPP_NULL;
predicateStackTail_ = &rootPredicateNode_;
}
@@ -88,7 +89,7 @@ TestResult& TestResult::addFailure(const char* file, unsigned int line,
/// added.
unsigned int nestingLevel = 0;
PredicateContext* lastNode = rootPredicateNode_.next_;
for (; lastNode != nullptr; lastNode = lastNode->next_) {
for (; lastNode != JSONCPP_NULL; lastNode = lastNode->next_) {
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
{
lastUsedPredicateId_ = lastNode->id_;
@@ -121,17 +122,18 @@ void TestResult::addFailureInfo(const char* file, unsigned int line,
TestResult& TestResult::popPredicateContext() {
PredicateContext* lastNode = &rootPredicateNode_;
while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
while (lastNode->next_ != JSONCPP_NULL &&
lastNode->next_->next_ != JSONCPP_NULL) {
lastNode = lastNode->next_;
}
// Set message target to popped failure
PredicateContext* tail = lastNode->next_;
if (tail != nullptr && tail->failure_ != nullptr) {
if (tail != JSONCPP_NULL && tail->failure_ != JSONCPP_NULL) {
messageTarget_ = tail->failure_;
}
// Remove tail from list
predicateStackTail_ = lastNode;
lastNode->next_ = nullptr;
lastNode->next_ = JSONCPP_NULL;
return *this;
}
@@ -147,7 +149,9 @@ void TestResult::printFailure(bool printTestName) const {
}
// 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, ' ');
if (failure.file_) {
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) {
if (messageTarget_ != nullptr) {
if (messageTarget_ != JSONCPP_NULL) {
messageTarget_->message_ += message;
}
return *this;
@@ -202,9 +206,9 @@ TestResult& TestResult::operator<<(bool value) {
// class TestCase
// //////////////////////////////////////////////////////////////////
TestCase::TestCase() = default;
TestCase::TestCase() : result_(JSONCPP_NULL) {}
TestCase::~TestCase() = default;
TestCase::~TestCase() {}
void TestCase::run(TestResult& result) {
result_ = &result;
@@ -214,7 +218,7 @@ void TestCase::run(TestResult& result) {
// class Runner
// //////////////////////////////////////////////////////////////////
Runner::Runner() = default;
Runner::Runner() {}
Runner& Runner::add(TestCaseFactory factory) {
tests_.push_back(factory);
@@ -267,19 +271,19 @@ bool Runner::runAllTest(bool printSummary) const {
printf("All %zu tests passed\n", count);
}
return true;
} else {
for (auto& result : failures) {
result.printFailure(count > 1);
}
if (printSummary) {
size_t const failedCount = failures.size();
size_t const passedCount = count - failedCount;
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
failedCount);
}
return false;
}
for (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 {
@@ -308,7 +312,8 @@ int Runner::runCommandLine(int argc, const char* argv[]) const {
if (opt == "--list-tests") {
listTests();
return 0;
} else if (opt == "--test-auto") {
}
if (opt == "--test-auto") {
preventDialogOnCrash();
} else if (opt == "--test") {
++index;

View File

@@ -61,7 +61,7 @@ public:
/// Not encapsulated to prevent step into when debugging failed assertions
/// Incremented by one on assertion predicate entry, decreased by one
/// by addPredicateContext().
PredicateContext::Id predicateId_{1};
PredicateContext::Id predicateId_;
/// \internal Implementation detail for predicate macros
PredicateContext* predicateStackTail_;
@@ -70,7 +70,7 @@ public:
/// Adds an assertion failure.
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
/// chained list.
@@ -84,7 +84,9 @@ public:
// Generic operator that will work with anything ostream can deal with.
template <typename T> TestResult& operator<<(const T& value) {
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());
}
@@ -106,9 +108,9 @@ private:
Failures failures_;
Json::String name_;
PredicateContext rootPredicateNode_;
PredicateContext::Id lastUsedPredicateId_{0};
PredicateContext::Id lastUsedPredicateId_;
/// Failure which is the target of the messages added using operator <<
Failure* messageTarget_{nullptr};
Failure* messageTarget_;
};
class TestCase {
@@ -122,7 +124,7 @@ public:
virtual const char* testName() const = 0;
protected:
TestResult* result_{nullptr};
TestResult* result_;
private:
virtual void runTestCase() = 0;
@@ -159,8 +161,8 @@ public:
static void printUsage(const char* appName);
private: // prevents copy construction and assignment
Runner(const Runner& other) = delete;
Runner& operator=(const Runner& other) = delete;
Runner(const Runner& other) JSONCPP_CTOR_DELETE;
Runner& operator=(const Runner& other) JSONCPP_CTOR_DELETE;
private:
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
/// fixture.
#define JSONTEST_ASSERT_PRED(expr) \
{ \
do { \
JsonTest::PredicateContext _minitest_Context = { \
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
result_->predicateStackTail_->next_ = &_minitest_Context; \
@@ -215,7 +217,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
result_->predicateStackTail_ = &_minitest_Context; \
(expr); \
result_->popPredicateContext(); \
}
} while (0)
/// \brief Asserts that two values are equals.
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
@@ -230,7 +232,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
/// \brief Asserts that a given expression throws an exception
#define JSONTEST_ASSERT_THROWS(expr) \
{ \
do { \
bool _threw = false; \
try { \
expr; \
@@ -240,7 +242,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
if (!_threw) \
result_->addFailure(__FILE__, __LINE__, \
"expected exception thrown: " #expr); \
}
} while (0)
/// \brief Begin a fixture test case.
#define JSONTEST_FIXTURE(FixtureType, name) \
@@ -251,8 +253,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
} \
\
public: /* overridden from TestCase */ \
const char* testName() const override { return #FixtureType "/" #name; } \
void runTestCase() override; \
const char* testName() const JSONCPP_OVERRIDE { \
return #FixtureType "/" #name; \
} \
void runTestCase() JSONCPP_OVERRIDE; \
}; \
\
void Test##FixtureType##name::runTestCase()
@@ -276,8 +280,10 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
} \
\
public: /* overridden from TestCase */ \
const char* testName() const override { return #FixtureType "/" #name; } \
void runTestCase() override; \
const char* testName() const JSONCPP_OVERRIDE { \
return #FixtureType "/" #name; \
} \
void runTestCase() JSONCPP_OVERRIDE; \
}; \
\
static bool test##FixtureType##name##collect = \

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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