mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 23:20:05 +02:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9059f5cad0 | ||
![]() |
45733df96c | ||
![]() |
5be07bdc5e | ||
![]() |
bf0cfa5b46 | ||
![]() |
cfc1ad72ad | ||
![]() |
c8453d39d1 | ||
![]() |
632044ad95 | ||
![]() |
b3189a0800 | ||
![]() |
9be5895985 | ||
![]() |
6aba23f4a8 | ||
![]() |
c161f4ac69 | ||
![]() |
75b360af4a | ||
![]() |
e36cff19f0 | ||
![]() |
b8cb8889aa | ||
![]() |
d2d4c74a03 | ||
![]() |
8b7ea09b80 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -28,7 +28,6 @@
|
||||
|
||||
# CMake-generated files:
|
||||
CMakeFiles/
|
||||
*.cmake
|
||||
/pkg-config/jsoncpp.pc
|
||||
jsoncpp_lib_static.dir/
|
||||
|
||||
|
156
.travis.yml
156
.travis.yml
@@ -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,74 +30,27 @@ matrix:
|
||||
osx_image: xcode11
|
||||
compiler: clang
|
||||
env:
|
||||
CXX="clang++"
|
||||
CC="clang"
|
||||
LIB_TYPE=static
|
||||
BUILD_TYPE=release
|
||||
LANGUAGE_STANDARD="11"
|
||||
CXX="clang++"
|
||||
CC="clang"
|
||||
LIB_TYPE=static
|
||||
BUILD_TYPE=release
|
||||
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
|
||||
LANGUAGE_STANDARD="11"
|
||||
CXX="clang++"
|
||||
CC="clang"
|
||||
LIB_TYPE=static
|
||||
BUILD_TYPE=release
|
||||
# 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-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
|
||||
- name: Linux xenial gcc cmake coverage
|
||||
os: linux
|
||||
dist: xenial
|
||||
compiler: gcc
|
||||
@@ -109,77 +62,10 @@ 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
|
||||
- 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
|
||||
- coveralls --include src/lib_json --include include
|
||||
notifications:
|
||||
email: false
|
||||
|
@@ -66,7 +66,7 @@ cmake --version
|
||||
echo ${CXX}
|
||||
${CXX} --version
|
||||
_COMPILER_NAME=`basename ${CXX}`
|
||||
if [ "${BUILD_TYPE}" = "shared" ]; then
|
||||
if [ "${LIB_TYPE}" = "shared" ]; then
|
||||
_CMAKE_BUILD_SHARED_LIBS=ON
|
||||
else
|
||||
_CMAKE_BUILD_SHARED_LIBS=OFF
|
||||
@@ -98,14 +98,6 @@ 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}"
|
||||
@@ -120,7 +112,6 @@ 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
|
||||
|
@@ -64,15 +64,11 @@ 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
|
||||
|
2
AUTHORS
2
AUTHORS
@@ -21,7 +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
|
||||
chenguoping <chenguopingdota@163.com>
|
||||
Chris Gilling <cgilling@iparadigms.com>
|
||||
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||
Christopher Dunn <cdunn2001@gmail.com>
|
||||
|
101
CMakeLists.txt
101
CMakeLists.txt
@@ -37,12 +37,20 @@ foreach(pold "") # Currently Empty
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
# Build the library with C++11 standard support, independent from other including
|
||||
# software which may use a different CXX_STANDARD or CMAKE_CXX_STANDARD.
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
# 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()
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# use ccache if found, has to be done before project()
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -53,47 +61,19 @@ if(CCACHE_EXECUTABLE)
|
||||
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
|
||||
endif()
|
||||
|
||||
# Note: project(VERSION XX) - the VERSION here is number, but VERSION in meson is string.
|
||||
# Thus, it is better to be consistent.
|
||||
project(JSONCPP
|
||||
project(jsoncpp
|
||||
# Note: version must be updated in three places when doing a release. This
|
||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||
# correct version.
|
||||
# 1. ./meson.build
|
||||
# 2. ./include/json/version.h
|
||||
# 3. ./CMakeLists.txt
|
||||
# IMPORTANT: also update the PROJECT_SOVERSION!!
|
||||
VERSION 1.9.4 # <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}")
|
||||
#if(NOT JSONCPP_VERSION_FOUND)
|
||||
# message(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
|
||||
#endif(NOT JSONCPP_VERSION_FOUND)
|
||||
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||
set(PROJECT_SOVERSION 24)
|
||||
|
||||
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)
|
||||
@@ -102,37 +82,9 @@ option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C
|
||||
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)
|
||||
|
||||
## 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()
|
||||
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
|
||||
option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
|
||||
option(BUILD_OBJECT_LIBS "Build jsoncpp_lib as a object library." ON)
|
||||
|
||||
# Adhere to GNU filesystem layout conventions
|
||||
include(GNUInstallDirs)
|
||||
@@ -179,7 +131,7 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# not yet ready for -Wsign-conversion
|
||||
|
||||
if(JSONCPP_WITH_STRICT_ISO)
|
||||
add_compile_options(-Wall)
|
||||
add_compile_options(-Wpedantic)
|
||||
endif()
|
||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
add_compile_options(-Werror=conversion)
|
||||
@@ -198,6 +150,11 @@ if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||
endif()
|
||||
|
||||
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||
include(JoinPaths)
|
||||
|
||||
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
|
||||
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
|
||||
|
||||
configure_file(
|
||||
"pkg-config/jsoncpp.pc.in"
|
||||
"pkg-config/jsoncpp.pc"
|
||||
@@ -212,7 +169,7 @@ if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
||||
FILE jsoncppConfig.cmake)
|
||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
||||
VERSION ${JSONCPP_VERSION}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
COMPATIBILITY SameMajorVersion)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||
|
22
README.md
22
README.md
@@ -1,5 +1,11 @@
|
||||
# JsonCpp
|
||||
|
||||
[](https://bintray.com/theirix/conan-repo/jsoncpp%3Atheirix)
|
||||
[](https://github.com/open-source-parsers/jsoncpp/blob/master/LICENSE)
|
||||
[](http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html)
|
||||
[](https://coveralls.io/github/open-source-parsers/jsoncpp?branch=master)
|
||||
|
||||
|
||||
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
||||
numbers, strings, ordered sequences of values, and collections of name/value
|
||||
pairs.
|
||||
@@ -11,13 +17,6 @@ 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
|
||||
|
||||
@@ -31,9 +30,14 @@ but can hardly applied into 0.y.z.
|
||||
|
||||
* `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`
|
||||
* `00.11.z` can be used both in old and new compilers.
|
||||
* Major versions maintain binary-compatibility.
|
||||
|
||||
### Special note
|
||||
The branch `00.11.z`is a new branch, its major version number `00` is to show that it is
|
||||
different from `0.y.z` and `1.y.z`, the main purpose of this branch is to make a balance
|
||||
between the other two branches. Thus, users can use some new features in this new branch
|
||||
that introduced in 1.y.z, but can hardly applied into 0.y.z.
|
||||
|
||||
## Using JsonCpp in your project
|
||||
|
||||
@@ -44,7 +48,7 @@ You can download and install JsonCpp using the [vcpkg](https://github.com/Micros
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
vcpkg install jsoncpp
|
||||
./vcpkg install jsoncpp
|
||||
|
||||
The JsonCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
|
23
cmake/JoinPaths.cmake
Normal file
23
cmake/JoinPaths.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
# This module provides a function for joining paths
|
||||
# known from most languages
|
||||
#
|
||||
# SPDX-License-Identifier: (MIT OR CC0-1.0)
|
||||
# Copyright 2020 Jan Tojnar
|
||||
# https://github.com/jtojnar/cmake-snips
|
||||
#
|
||||
# Modelled after Python’s os.path.join
|
||||
# https://docs.python.org/3.7/library/os.path.html#os.path.join
|
||||
# Windows not supported
|
||||
function(join_paths joined_path first_path_segment)
|
||||
set(temp_path "${first_path_segment}")
|
||||
foreach(current_segment IN LISTS ARGN)
|
||||
if(NOT ("${current_segment}" STREQUAL ""))
|
||||
if(IS_ABSOLUTE "${current_segment}")
|
||||
set(temp_path "${current_segment}")
|
||||
else()
|
||||
set(temp_path "${temp_path}/${current_segment}")
|
||||
endif()
|
||||
endif()
|
||||
endforeach()
|
||||
set(${joined_path} "${temp_path}" PARENT_SCOPE)
|
||||
endfunction()
|
@@ -1,5 +1,4 @@
|
||||
#include "json/json.h"
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
/** \brief Parse from stream, collect comments and capture error info.
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#include "json/json.h"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
/**
|
||||
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
||||
@@ -11,9 +10,9 @@
|
||||
* 20
|
||||
*/
|
||||
int main() {
|
||||
const std::string rawJson = "{\"Age\": 20, \"Name\": \"colin\"}";
|
||||
const int rawJsonLength = static_cast<int>(rawJson.length());
|
||||
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
||||
const auto rawJsonLength = static_cast<int>(rawJson.length());
|
||||
constexpr bool shouldUseOldWay = false;
|
||||
JSONCPP_STRING err;
|
||||
Json::Value root;
|
||||
|
||||
@@ -22,13 +21,12 @@ int main() {
|
||||
reader.parse(rawJson, root);
|
||||
} else {
|
||||
Json::CharReaderBuilder builder;
|
||||
Json::CharReader* reader(builder.newCharReader());
|
||||
const std::unique_ptr<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();
|
||||
|
@@ -12,11 +12,11 @@
|
||||
int main() {
|
||||
Json::Value root;
|
||||
Json::StreamWriterBuilder builder;
|
||||
Json::StreamWriter* writer(builder.newStreamWriter());
|
||||
const std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
|
||||
|
||||
root["Name"] = "robin";
|
||||
root["Age"] = 20;
|
||||
writer->write(root, &std::cout);
|
||||
delete writer;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
#include "json/json.h"
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
/** \brief Write a Value object to a string.
|
||||
* Example Usage:
|
||||
@@ -16,7 +15,7 @@
|
||||
int main() {
|
||||
Json::Value root;
|
||||
Json::Value data;
|
||||
JSONCPP_CONST bool shouldUseOldWay = false;
|
||||
constexpr bool shouldUseOldWay = false;
|
||||
root["action"] = "run";
|
||||
data["number"] = 1;
|
||||
root["data"] = data;
|
||||
|
@@ -58,10 +58,4 @@
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#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
|
||||
|
@@ -5,20 +5,14 @@
|
||||
|
||||
#ifndef JSON_CONFIG_H_INCLUDED
|
||||
#define JSON_CONFIG_H_INCLUDED
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <istream>
|
||||
#include <memory>
|
||||
#include <ostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
#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
|
||||
#include <type_traits>
|
||||
|
||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||
// assertion macros. The default is to use exceptions.
|
||||
@@ -56,6 +50,11 @@
|
||||
#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
|
||||
@@ -71,41 +70,10 @@ 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
|
||||
|
||||
#if __cplusplus >= 201103L || defined(_MSC_VER)
|
||||
#define JSONCPP_OP_EXPLICIT explicit
|
||||
#else
|
||||
#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
|
||||
// JSONCPP_OVERRIDE is maintained for backwards compatibility of external tools.
|
||||
// C++11 should be used directly in JSONCPP.
|
||||
#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)))
|
||||
@@ -130,36 +98,33 @@ 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;
|
||||
using Int = int;
|
||||
using UInt = unsigned int;
|
||||
#if defined(JSON_NO_INT64)
|
||||
typedef int LargestInt;
|
||||
typedef unsigned int LargestUInt;
|
||||
using LargestInt = int;
|
||||
using LargestUInt = unsigned int;
|
||||
#undef JSON_HAS_INT64
|
||||
#else // if defined(JSON_NO_INT64)
|
||||
// For Microsoft Visual use specific types as long long is not supported
|
||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
using Int64 = __int64;
|
||||
using UInt64 = unsigned __int64;
|
||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||
typedef int64_t Int64;
|
||||
typedef uint64_t UInt64;
|
||||
using Int64 = int64_t;
|
||||
using UInt64 = uint64_t;
|
||||
#endif // if defined(_MSC_VER)
|
||||
typedef Int64 LargestInt;
|
||||
typedef UInt64 LargestUInt;
|
||||
using LargestInt = Int64;
|
||||
using LargestUInt = UInt64;
|
||||
#define JSON_HAS_INT64
|
||||
#endif // if defined(JSON_NO_INT64)
|
||||
|
||||
#if JSONCPP_CXX_STD_11
|
||||
template <typename T>
|
||||
using Allocator =
|
||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
||||
@@ -173,20 +138,13 @@ 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).
|
||||
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;
|
||||
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;
|
||||
|
||||
#endif // JSON_CONFIG_H_INCLUDED
|
||||
|
@@ -29,7 +29,7 @@ class CharReaderBuilder;
|
||||
class Features;
|
||||
|
||||
// value.h
|
||||
typedef unsigned int ArrayIndex;
|
||||
using ArrayIndex = unsigned int;
|
||||
class StaticString;
|
||||
class Path;
|
||||
class PathArgument;
|
||||
|
@@ -41,17 +41,17 @@ public:
|
||||
Features();
|
||||
|
||||
/// \c true if comments are allowed. Default: \c true.
|
||||
bool allowComments_;
|
||||
bool allowComments_{true};
|
||||
|
||||
/// \c true if root must be either an array or an object value. Default: \c
|
||||
/// false.
|
||||
bool strictRoot_;
|
||||
bool strictRoot_{false};
|
||||
|
||||
/// \c true if dropped null placeholders are allowed. Default: \c false.
|
||||
bool allowDroppedNullPlaceholders_;
|
||||
bool allowDroppedNullPlaceholders_{false};
|
||||
|
||||
/// \c true if numeric object key are allowed. Default: \c false.
|
||||
bool allowNumericKeys_;
|
||||
bool allowNumericKeys_{false};
|
||||
};
|
||||
|
||||
} // namespace Json
|
||||
|
@@ -36,8 +36,8 @@ namespace Json {
|
||||
class JSONCPP_DEPRECATED(
|
||||
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char* Location;
|
||||
using Char = char;
|
||||
using Location = const Char*;
|
||||
|
||||
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||
*
|
||||
@@ -187,7 +187,7 @@ private:
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
using Errors = std::deque<ErrorInfo>;
|
||||
|
||||
bool readToken(Token& token);
|
||||
void skipSpaces();
|
||||
@@ -210,8 +210,7 @@ private:
|
||||
unsigned int& unicode);
|
||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||
Location end, unsigned int& unicode);
|
||||
bool addError(const String& message, Token& token,
|
||||
Location extra = JSONCPP_NULL);
|
||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
||||
bool recoverFromError(TokenType skipUntilToken);
|
||||
bool addErrorAndRecover(const String& message, Token& token,
|
||||
TokenType skipUntilToken);
|
||||
@@ -227,25 +226,25 @@ private:
|
||||
static bool containsNewLine(Location begin, Location end);
|
||||
static String normalizeEOL(Location begin, Location end);
|
||||
|
||||
typedef std::stack<Value*> Nodes;
|
||||
using Nodes = std::stack<Value*>;
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
String document_;
|
||||
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() {}
|
||||
virtual ~CharReader() = default;
|
||||
/** \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.
|
||||
@@ -267,7 +266,7 @@ public:
|
||||
|
||||
class JSON_API Factory {
|
||||
public:
|
||||
virtual ~Factory() {}
|
||||
virtual ~Factory() = default;
|
||||
/** \brief Allocate a CharReader via operator new().
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
@@ -333,9 +332,9 @@ public:
|
||||
Json::Value settings_;
|
||||
|
||||
CharReaderBuilder();
|
||||
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||
~CharReaderBuilder() override;
|
||||
|
||||
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||
CharReader* newCharReader() const override;
|
||||
|
||||
/** \return true if 'settings' are legal and consistent;
|
||||
* otherwise, indicate bad settings via 'invalid'.
|
||||
|
@@ -13,16 +13,13 @@
|
||||
// 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)
|
||||
#if defined(_MSC_VER) && _MSC_VER == 1800
|
||||
#define JSONCPP_NORETURN __declspec(noreturn)
|
||||
#elif defined(__GNUC__) || defined(__clang__)
|
||||
#define JSONCPP_NORETURN __attribute__((noreturn))
|
||||
#else
|
||||
#define JSONCPP_NORETURN
|
||||
#define JSONCPP_NORETURN [[noreturn]]
|
||||
#endif
|
||||
#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
|
||||
@@ -42,15 +39,10 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if JSONCPP_CXX_STD_11
|
||||
#else
|
||||
#undef JSONCPP_TEMPLATE_DELETE
|
||||
#define JSONCPP_TEMPLATE_DELETE
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#include <array>
|
||||
#include <exception>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -75,8 +67,8 @@ namespace Json {
|
||||
class JSON_API Exception : public std::exception {
|
||||
public:
|
||||
Exception(String msg);
|
||||
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||
~Exception() noexcept override;
|
||||
char const* what() const noexcept override;
|
||||
|
||||
protected:
|
||||
String msg_;
|
||||
@@ -154,7 +146,7 @@ enum PrecisionType {
|
||||
*/
|
||||
class JSON_API StaticString {
|
||||
public:
|
||||
JSONCPP_OP_EXPLICIT StaticString(const char* czstring) : c_str_(czstring) {}
|
||||
explicit StaticString(const char* czstring) : c_str_(czstring) {}
|
||||
|
||||
operator const char*() const { return c_str_; }
|
||||
|
||||
@@ -202,21 +194,21 @@ class JSON_API Value {
|
||||
friend class ValueIteratorBase;
|
||||
|
||||
public:
|
||||
typedef std::vector<String> Members;
|
||||
typedef ValueIterator iterator;
|
||||
typedef ValueConstIterator const_iterator;
|
||||
typedef Json::UInt UInt;
|
||||
typedef Json::Int Int;
|
||||
using Members = std::vector<String>;
|
||||
using iterator = ValueIterator;
|
||||
using const_iterator = ValueConstIterator;
|
||||
using UInt = Json::UInt;
|
||||
using Int = Json::Int;
|
||||
#if defined(JSON_HAS_INT64)
|
||||
typedef Json::UInt64 UInt64;
|
||||
typedef Json::Int64 Int64;
|
||||
using UInt64 = Json::UInt64;
|
||||
using Int64 = Json::Int64;
|
||||
#endif // defined(JSON_HAS_INT64)
|
||||
typedef Json::LargestInt LargestInt;
|
||||
typedef Json::LargestUInt LargestUInt;
|
||||
typedef Json::ArrayIndex ArrayIndex;
|
||||
using LargestInt = Json::LargestInt;
|
||||
using LargestUInt = Json::LargestUInt;
|
||||
using ArrayIndex = Json::ArrayIndex;
|
||||
|
||||
// Required for boost integration, e. g. BOOST_TEST
|
||||
typedef std::string value_type;
|
||||
using value_type = std::string;
|
||||
|
||||
#if JSON_USE_NULLREF
|
||||
// Binary compatibility kludges, do not use.
|
||||
@@ -228,35 +220,34 @@ public:
|
||||
static Value const& nullSingleton();
|
||||
|
||||
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST LargestInt minLargestInt =
|
||||
static constexpr LargestInt minLargestInt =
|
||||
LargestInt(~(LargestUInt(-1) / 2));
|
||||
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST LargestInt maxLargestInt =
|
||||
LargestInt(LargestUInt(-1) / 2);
|
||||
static constexpr LargestInt maxLargestInt = LargestInt(LargestUInt(-1) / 2);
|
||||
/// Maximum unsigned integer value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST LargestUInt maxLargestUInt = LargestUInt(-1);
|
||||
static constexpr LargestUInt maxLargestUInt = LargestUInt(-1);
|
||||
|
||||
/// Minimum signed int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST Int minInt = Int(~(UInt(-1) / 2));
|
||||
static constexpr Int minInt = Int(~(UInt(-1) / 2));
|
||||
/// Maximum signed int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST Int maxInt = Int(UInt(-1) / 2);
|
||||
static constexpr Int maxInt = Int(UInt(-1) / 2);
|
||||
/// Maximum unsigned int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST UInt maxUInt = UInt(-1);
|
||||
static constexpr UInt maxUInt = UInt(-1);
|
||||
|
||||
#if defined(JSON_HAS_INT64)
|
||||
/// Minimum signed 64 bits int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
||||
static constexpr Int64 minInt64 = Int64(~(UInt64(-1) / 2));
|
||||
/// Maximum signed 64 bits int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
||||
static constexpr Int64 maxInt64 = Int64(UInt64(-1) / 2);
|
||||
/// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
|
||||
static JSONCPP_CONST UInt64 maxUInt64 = UInt64(-1);
|
||||
static constexpr UInt64 maxUInt64 = UInt64(-1);
|
||||
#endif // defined(JSON_HAS_INT64)
|
||||
/// Default precision for real value for string representation.
|
||||
static JSONCPP_CONST UInt defaultRealPrecision = 17;
|
||||
static constexpr 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 JSONCPP_CONST double maxUInt64AsDouble = 18446744073709551615.0;
|
||||
static constexpr 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
|
||||
@@ -272,14 +263,11 @@ 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;
|
||||
@@ -354,18 +342,15 @@ public:
|
||||
Value(const StaticString& value);
|
||||
Value(const String& value);
|
||||
Value(bool value);
|
||||
Value(std::nullptr_t ptr) = delete;
|
||||
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);
|
||||
@@ -437,7 +422,7 @@ public:
|
||||
bool empty() const;
|
||||
|
||||
/// Return !isNull()
|
||||
JSONCPP_OP_EXPLICIT operator bool() const;
|
||||
explicit operator bool() const;
|
||||
|
||||
/// Remove all object members and array elements.
|
||||
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||
@@ -478,15 +463,11 @@ 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, 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.
|
||||
@@ -582,11 +563,15 @@ public:
|
||||
|
||||
/// \deprecated Always pass len.
|
||||
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
||||
void setComment(const char* comment, CommentPlacement placement);
|
||||
void setComment(const char* comment, CommentPlacement placement) {
|
||||
setComment(String(comment, strlen(comment)), placement);
|
||||
}
|
||||
/// Comments must be //... or /* ... */
|
||||
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||
void setComment(const char* comment, size_t len, CommentPlacement placement) {
|
||||
setComment(String(comment, len), placement);
|
||||
}
|
||||
/// Comments must be //... or /* ... */
|
||||
void setComment(const String& comment, CommentPlacement placement);
|
||||
void setComment(String comment, CommentPlacement placement);
|
||||
bool hasComment(CommentPlacement placement) const;
|
||||
/// Include delimiters and embedded newlines.
|
||||
String getComment(CommentPlacement placement) const;
|
||||
@@ -648,15 +633,18 @@ private:
|
||||
|
||||
class Comments {
|
||||
public:
|
||||
Comments() {}
|
||||
Comments() = default;
|
||||
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 s);
|
||||
void set(CommentPlacement slot, String comment);
|
||||
|
||||
private:
|
||||
String ptr_[numberOfCommentPlacement];
|
||||
using Array = std::array<String, numberOfCommentPlacement>;
|
||||
std::unique_ptr<Array> ptr_;
|
||||
};
|
||||
Comments comments_;
|
||||
|
||||
@@ -711,8 +699,8 @@ public:
|
||||
private:
|
||||
enum Kind { kindNone = 0, kindIndex, kindKey };
|
||||
String key_;
|
||||
ArrayIndex index_;
|
||||
Kind kind_;
|
||||
ArrayIndex index_{};
|
||||
Kind kind_{kindNone};
|
||||
};
|
||||
|
||||
/** \brief Experimental and untested: represents a "path" to access a node.
|
||||
@@ -741,8 +729,8 @@ public:
|
||||
Value& make(Value& root) const;
|
||||
|
||||
private:
|
||||
typedef std::vector<const PathArgument*> InArgs;
|
||||
typedef std::vector<PathArgument> Args;
|
||||
using InArgs = std::vector<const PathArgument*>;
|
||||
using Args = std::vector<PathArgument>;
|
||||
|
||||
void makePath(const String& path, const InArgs& in);
|
||||
void addPathInArg(const String& path, const InArgs& in,
|
||||
@@ -757,10 +745,10 @@ private:
|
||||
*/
|
||||
class JSON_API ValueIteratorBase {
|
||||
public:
|
||||
typedef std::bidirectional_iterator_tag iterator_category;
|
||||
typedef unsigned int size_t;
|
||||
typedef int difference_type;
|
||||
typedef ValueIteratorBase SelfType;
|
||||
using iterator_category = std::bidirectional_iterator_tag;
|
||||
using size_t = unsigned int;
|
||||
using difference_type = int;
|
||||
using SelfType = ValueIteratorBase;
|
||||
|
||||
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||
|
||||
@@ -817,14 +805,13 @@ protected:
|
||||
private:
|
||||
Value::ObjectValues::iterator current_;
|
||||
// Indicates that iterator is for a null value.
|
||||
bool isNull_;
|
||||
bool isNull_{true};
|
||||
|
||||
public:
|
||||
// For some reason, BORLAND needs these at the end, rather
|
||||
// than earlier. No idea why.
|
||||
ValueIteratorBase();
|
||||
JSONCPP_OP_EXPLICIT
|
||||
ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||
};
|
||||
|
||||
/** \brief const iterator for object and array value.
|
||||
@@ -834,12 +821,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
|
||||
friend class Value;
|
||||
|
||||
public:
|
||||
typedef const Value value_type;
|
||||
using value_type = const Value;
|
||||
// typedef unsigned int size_t;
|
||||
// typedef int difference_type;
|
||||
typedef const Value& reference;
|
||||
typedef const Value* pointer;
|
||||
typedef ValueConstIterator SelfType;
|
||||
using reference = const Value&;
|
||||
using pointer = const Value*;
|
||||
using SelfType = ValueConstIterator;
|
||||
|
||||
ValueConstIterator();
|
||||
ValueConstIterator(ValueIterator const& other);
|
||||
@@ -847,8 +834,7 @@ public:
|
||||
private:
|
||||
/*! \internal Use by Value to create an iterator.
|
||||
*/
|
||||
JSONCPP_OP_EXPLICIT
|
||||
ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
|
||||
|
||||
public:
|
||||
SelfType& operator=(const ValueIteratorBase& other);
|
||||
@@ -886,22 +872,21 @@ class JSON_API ValueIterator : public ValueIteratorBase {
|
||||
friend class Value;
|
||||
|
||||
public:
|
||||
typedef Value value_type;
|
||||
typedef unsigned int size_t;
|
||||
typedef int difference_type;
|
||||
typedef Value& reference;
|
||||
typedef Value* pointer;
|
||||
typedef ValueIterator SelfType;
|
||||
using value_type = Value;
|
||||
using size_t = unsigned int;
|
||||
using difference_type = int;
|
||||
using reference = Value&;
|
||||
using pointer = Value*;
|
||||
using SelfType = ValueIterator;
|
||||
|
||||
ValueIterator();
|
||||
JSONCPP_OP_EXPLICIT ValueIterator(const ValueConstIterator& other);
|
||||
explicit ValueIterator(const ValueConstIterator& other);
|
||||
ValueIterator(const ValueIterator& other);
|
||||
|
||||
private:
|
||||
/*! \internal Use by Value to create an iterator.
|
||||
*/
|
||||
JSONCPP_OP_EXPLICIT
|
||||
ValueIterator(const Value::ObjectValues::iterator& current);
|
||||
explicit ValueIterator(const Value::ObjectValues::iterator& current);
|
||||
|
||||
public:
|
||||
SelfType& operator=(const SelfType& other);
|
||||
|
@@ -9,10 +9,10 @@
|
||||
// 3. /CMakeLists.txt
|
||||
// IMPORTANT: also update the SOVERSION!!
|
||||
|
||||
#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_STRING "1.9.4"
|
||||
#define JSONCPP_VERSION_MAJOR 1
|
||||
#define JSONCPP_VERSION_MINOR 9
|
||||
#define JSONCPP_VERSION_PATCH 3
|
||||
#define JSONCPP_VERSION_QUALIFIER
|
||||
#define JSONCPP_VERSION_HEXA \
|
||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||
|
@@ -119,12 +119,12 @@ public:
|
||||
Json::Value settings_;
|
||||
|
||||
StreamWriterBuilder();
|
||||
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||
~StreamWriterBuilder() override;
|
||||
|
||||
/**
|
||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||
*/
|
||||
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||
StreamWriter* newStreamWriter() const 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() JSONCPP_OVERRIDE {}
|
||||
~FastWriter() override = default;
|
||||
|
||||
void enableYAMLCompatibility();
|
||||
|
||||
@@ -183,15 +183,15 @@ public:
|
||||
void omitEndingLineFeed();
|
||||
|
||||
public: // overridden from Writer
|
||||
String write(const Value& root) JSONCPP_OVERRIDE;
|
||||
String write(const Value& root) override;
|
||||
|
||||
private:
|
||||
void writeValue(const Value& value);
|
||||
|
||||
String document_;
|
||||
bool yamlCompatibilityEnabled_;
|
||||
bool dropNullPlaceholders_;
|
||||
bool omitEndingLineFeed_;
|
||||
bool yamlCompatibilityEnabled_{false};
|
||||
bool dropNullPlaceholders_{false};
|
||||
bool omitEndingLineFeed_{false};
|
||||
};
|
||||
#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() JSONCPP_OVERRIDE {}
|
||||
~StyledWriter() override = default;
|
||||
|
||||
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) JSONCPP_OVERRIDE;
|
||||
String write(const Value& root) override;
|
||||
|
||||
private:
|
||||
void writeValue(const Value& value);
|
||||
@@ -252,14 +252,14 @@ private:
|
||||
static bool hasCommentForValue(const Value& value);
|
||||
static String normalizeEOL(const String& text);
|
||||
|
||||
typedef std::vector<String> ChildValues;
|
||||
using ChildValues = std::vector<String>;
|
||||
|
||||
ChildValues childValues_;
|
||||
String document_;
|
||||
String indentString_;
|
||||
unsigned int rightMargin_;
|
||||
unsigned int indentSize_;
|
||||
bool addChildValues_;
|
||||
unsigned int rightMargin_{74};
|
||||
unsigned int indentSize_{3};
|
||||
bool addChildValues_{false};
|
||||
};
|
||||
#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() {}
|
||||
~StyledStreamWriter() = default;
|
||||
|
||||
public:
|
||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||
@@ -326,12 +326,12 @@ private:
|
||||
static bool hasCommentForValue(const Value& value);
|
||||
static String normalizeEOL(const String& text);
|
||||
|
||||
typedef std::vector<String> ChildValues;
|
||||
using ChildValues = std::vector<String>;
|
||||
|
||||
ChildValues childValues_;
|
||||
OStream* document_;
|
||||
String indentString_;
|
||||
unsigned int rightMargin_;
|
||||
unsigned int rightMargin_{74};
|
||||
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 = significantDigits);
|
||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
||||
String JSON_API valueToString(bool value);
|
||||
String JSON_API valueToQuotedString(const char* value);
|
||||
|
||||
|
@@ -9,7 +9,7 @@ project(
|
||||
# 2. /include/json/version.h
|
||||
# 3. /CMakeLists.txt
|
||||
# IMPORTANT: also update the SOVERSION!!
|
||||
version : '00.11.0',
|
||||
version : '1.9.4',
|
||||
default_options : [
|
||||
'buildtype=release',
|
||||
'cpp_std=c++11',
|
||||
@@ -50,7 +50,7 @@ jsoncpp_lib = library(
|
||||
'src/lib_json/json_value.cpp',
|
||||
'src/lib_json/json_writer.cpp',
|
||||
]),
|
||||
soversion : 23,
|
||||
soversion : 24,
|
||||
install : true,
|
||||
include_directories : jsoncpp_include_directories,
|
||||
cpp_args: dll_export_flag)
|
||||
@@ -73,7 +73,7 @@ if meson.is_subproject() or not get_option('tests')
|
||||
subdir_done()
|
||||
endif
|
||||
|
||||
python = import('python').find_installation('python3')
|
||||
python = import('python').find_installation()
|
||||
|
||||
jsoncpp_test = executable(
|
||||
'jsoncpp_test', files([
|
||||
|
@@ -1,7 +1,7 @@
|
||||
prefix=@CMAKE_INSTALL_PREFIX@
|
||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
|
||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
||||
libdir=@libdir_for_pc_file@
|
||||
includedir=@includedir_for_pc_file@
|
||||
|
||||
Name: jsoncpp
|
||||
Description: A C++ library for interacting with JSON
|
||||
|
@@ -19,8 +19,10 @@ if(BUILD_SHARED_LIBS)
|
||||
else()
|
||||
add_definitions(-DJSON_DLL)
|
||||
endif()
|
||||
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
||||
else()
|
||||
target_link_libraries(jsontestrunner_exe jsoncpp_static)
|
||||
endif()
|
||||
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
||||
|
||||
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
||||
|
||||
|
@@ -24,9 +24,7 @@ struct Options {
|
||||
Json::String path;
|
||||
Json::Features features;
|
||||
bool parseOnly;
|
||||
|
||||
typedef Json::String (*writeFuncType)(Json::Value const&);
|
||||
|
||||
using writeFuncType = Json::String (*)(Json::Value const&);
|
||||
writeFuncType write;
|
||||
};
|
||||
|
||||
@@ -59,11 +57,11 @@ static Json::String readInputTestFile(const char* path) {
|
||||
if (!file)
|
||||
return "";
|
||||
fseek(file, 0, SEEK_END);
|
||||
long const size = ftell(file);
|
||||
size_t const usize = static_cast<size_t>(size);
|
||||
auto const size = ftell(file);
|
||||
auto const usize = static_cast<size_t>(size);
|
||||
fseek(file, 0, SEEK_SET);
|
||||
char* buffer = new char[usize + 1];
|
||||
buffer[usize] = 0;
|
||||
auto buffer = new char[size + 1];
|
||||
buffer[size] = 0;
|
||||
Json::String text;
|
||||
if (fread(buffer, 1, usize, file) == usize)
|
||||
text = buffer;
|
||||
@@ -113,9 +111,7 @@ static void printValueTree(FILE* fout, Json::Value& value,
|
||||
Json::Value::Members members(value.getMemberNames());
|
||||
std::sort(members.begin(), members.end());
|
||||
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||
for (Json::Value::Members::const_iterator it = members.begin();
|
||||
it != members.end(); it++) {
|
||||
const Json::String& name = *it;
|
||||
for (const auto& name : members) {
|
||||
printValueTree(fout, value[name], path + suffix + name);
|
||||
}
|
||||
} break;
|
||||
@@ -142,7 +138,7 @@ static int parseAndSaveValueTree(const Json::String& input,
|
||||
features.allowDroppedNullPlaceholders_;
|
||||
builder.settings_["allowNumericKeys"] = features.allowNumericKeys_;
|
||||
|
||||
Json::CharReader* reader(builder.newCharReader());
|
||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
Json::String errors;
|
||||
const bool parsingSuccessful =
|
||||
reader->parse(input.data(), input.data() + input.size(), root, &errors);
|
||||
@@ -152,7 +148,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 {
|
||||
|
@@ -50,7 +50,7 @@ set(PUBLIC_HEADERS
|
||||
|
||||
source_group("Public API" FILES ${PUBLIC_HEADERS})
|
||||
|
||||
set(jsoncpp_sources
|
||||
set(JSONCPP_SOURCES
|
||||
json_tool.h
|
||||
json_reader.cpp
|
||||
json_valueiterator.inl
|
||||
@@ -65,33 +65,10 @@ else()
|
||||
set(INSTALL_EXPORT)
|
||||
endif()
|
||||
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions(JSON_DLL_BUILD)
|
||||
else()
|
||||
add_definitions(-DJSON_DLL_BUILD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
||||
set_target_properties( jsoncpp_lib PROPERTIES
|
||||
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/.")
|
||||
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
|
||||
list(APPEND REQUIRED_FEATURES
|
||||
cxx_std_11 # Compiler mode is aware of C++ 11.
|
||||
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
||||
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
|
||||
@@ -137,21 +114,107 @@ 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)
|
||||
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||
add_compile_definitions(JSON_DLL_BUILD)
|
||||
else()
|
||||
add_definitions(-DJSON_DLL_BUILD)
|
||||
endif()
|
||||
|
||||
set(SHARED_LIB ${PROJECT_NAME}_lib)
|
||||
add_library(${SHARED_LIB} SHARED ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_SOVERSION}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${SHARED_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
target_include_directories(${SHARED_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${SHARED_LIB})
|
||||
endif()
|
||||
|
||||
install(TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
||||
if(BUILD_STATIC_LIBS)
|
||||
set(STATIC_LIB ${PROJECT_NAME}_static)
|
||||
add_library(${STATIC_LIB} STATIC ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
|
||||
# avoid name clashes on windows as the shared import lib is alse named jsoncpp.lib
|
||||
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
|
||||
set(STATIC_SUFFIX "_static")
|
||||
endif()
|
||||
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp${STATIC_SUFFIX}
|
||||
VERSION ${PROJECT_VERSION}
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${STATIC_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
target_include_directories(${STATIC_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${STATIC_LIB})
|
||||
endif()
|
||||
|
||||
if(BUILD_OBJECT_LIBS)
|
||||
set(OBJECT_LIB ${PROJECT_NAME}_object)
|
||||
add_library(${OBJECT_LIB} OBJECT ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||
|
||||
set_target_properties(${OBJECT_LIB} PROPERTIES
|
||||
OUTPUT_NAME jsoncpp
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_SOVERSION}
|
||||
POSITION_INDEPENDENT_CODE ON
|
||||
)
|
||||
|
||||
# Set library's runtime search path on OSX
|
||||
if(APPLE)
|
||||
set_target_properties(${OBJECT_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
|
||||
endif()
|
||||
|
||||
target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})
|
||||
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||
target_include_directories(${OBJECT_LIB} PUBLIC
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_TARGETS ${OBJECT_LIB})
|
||||
endif()
|
||||
|
||||
install(TARGETS ${CMAKE_TARGETS} ${INSTALL_EXPORT}
|
||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||
)
|
||||
|
||||
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>
|
||||
)
|
||||
endif()
|
||||
|
@@ -10,6 +10,7 @@
|
||||
#include <json/reader.h>
|
||||
#include <json/value.h>
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
@@ -51,15 +52,18 @@ static size_t const stackLimit_g =
|
||||
|
||||
namespace Json {
|
||||
|
||||
typedef CharReader* CharReaderPtr;
|
||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
||||
using CharReaderPtr = std::unique_ptr<CharReader>;
|
||||
#else
|
||||
using CharReaderPtr = std::auto_ptr<CharReader>;
|
||||
#endif
|
||||
|
||||
// Implementation of class Features
|
||||
// ////////////////////////////////
|
||||
|
||||
Features::Features()
|
||||
: allowComments_(true), strictRoot_(false),
|
||||
allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
|
||||
Features Features::all() { return Features(); }
|
||||
Features::Features() = default;
|
||||
|
||||
Features Features::all() { return {}; }
|
||||
|
||||
Features Features::strictMode() {
|
||||
Features features;
|
||||
@@ -74,24 +78,15 @@ Features Features::strictMode() {
|
||||
// ////////////////////////////////
|
||||
|
||||
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
|
||||
for (; begin < end; ++begin)
|
||||
if (*begin == '\n' || *begin == '\r')
|
||||
return true;
|
||||
return false;
|
||||
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
|
||||
}
|
||||
|
||||
// Class Reader
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
Reader::Reader()
|
||||
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||
lastValue_(), commentsBefore_(), features_(Features::all()),
|
||||
collectComments_() {}
|
||||
Reader::Reader() : features_(Features::all()) {}
|
||||
|
||||
Reader::Reader(const Features& features)
|
||||
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||
lastValue_(), commentsBefore_(), features_(features), collectComments_() {
|
||||
}
|
||||
Reader::Reader(const Features& features) : features_(features) {}
|
||||
|
||||
bool Reader::parse(const std::string& document, Value& root,
|
||||
bool collectComments) {
|
||||
@@ -124,8 +119,8 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||
end_ = endDoc;
|
||||
collectComments_ = collectComments;
|
||||
current_ = begin_;
|
||||
lastValueEnd_ = JSONCPP_NULL;
|
||||
lastValue_ = JSONCPP_NULL;
|
||||
lastValueEnd_ = nullptr;
|
||||
lastValue_ = nullptr;
|
||||
commentsBefore_.clear();
|
||||
errors_.clear();
|
||||
while (!nodes_.empty())
|
||||
@@ -379,7 +374,7 @@ void Reader::addComment(Location begin, Location end,
|
||||
assert(collectComments_);
|
||||
const String& normalized = normalizeEOL(begin, end);
|
||||
if (placement == commentAfterOnSameLine) {
|
||||
assert(lastValue_ != JSONCPP_NULL);
|
||||
assert(lastValue_ != nullptr);
|
||||
lastValue_->setComment(normalized, placement);
|
||||
} else {
|
||||
commentsBefore_ += normalized;
|
||||
@@ -568,7 +563,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
||||
Char c = *current++;
|
||||
if (c < '0' || c > '9')
|
||||
return decodeDouble(token, decoded);
|
||||
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||
auto digit(static_cast<Value::UInt>(c - '0'));
|
||||
if (value >= threshold) {
|
||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||
// a) we've only just touched the limit, b) this is the last digit, and
|
||||
@@ -801,9 +796,7 @@ String Reader::getFormatedErrorMessages() const {
|
||||
|
||||
String Reader::getFormattedErrorMessages() const {
|
||||
String formattedMessage;
|
||||
for (Errors::const_iterator itError = errors_.begin();
|
||||
itError != errors_.end(); ++itError) {
|
||||
const ErrorInfo& error = *itError;
|
||||
for (const auto& error : errors_) {
|
||||
formattedMessage +=
|
||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||
formattedMessage += " " + error.message_ + "\n";
|
||||
@@ -816,9 +809,7 @@ String Reader::getFormattedErrorMessages() const {
|
||||
|
||||
std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
||||
std::vector<Reader::StructuredError> allErrors;
|
||||
for (Errors::const_iterator itError = errors_.begin();
|
||||
itError != errors_.end(); ++itError) {
|
||||
const ErrorInfo& error = *itError;
|
||||
for (const auto& error : errors_) {
|
||||
Reader::StructuredError structured;
|
||||
structured.offset_start = error.token_.start_ - begin_;
|
||||
structured.offset_limit = error.token_.end_ - begin_;
|
||||
@@ -839,7 +830,7 @@ bool Reader::pushError(const Value& value, const String& message) {
|
||||
ErrorInfo info;
|
||||
info.token_ = token;
|
||||
info.message_ = message;
|
||||
info.extra_ = JSONCPP_NULL;
|
||||
info.extra_ = nullptr;
|
||||
errors_.push_back(info);
|
||||
return true;
|
||||
}
|
||||
@@ -882,7 +873,7 @@ public:
|
||||
size_t stackLimit_;
|
||||
}; // OurFeatures
|
||||
|
||||
OurFeatures OurFeatures::all() { return OurFeatures(); }
|
||||
OurFeatures OurFeatures::all() { return {}; }
|
||||
|
||||
// Implementation of class Reader
|
||||
// ////////////////////////////////
|
||||
@@ -891,15 +882,15 @@ OurFeatures OurFeatures::all() { return OurFeatures(); }
|
||||
// for implementing JSON reading.
|
||||
class OurReader {
|
||||
public:
|
||||
typedef char Char;
|
||||
typedef const Char* Location;
|
||||
using Char = char;
|
||||
using Location = const Char*;
|
||||
struct StructuredError {
|
||||
ptrdiff_t offset_start;
|
||||
ptrdiff_t offset_limit;
|
||||
String message;
|
||||
};
|
||||
|
||||
JSONCPP_OP_EXPLICIT OurReader(OurFeatures const& features);
|
||||
explicit OurReader(OurFeatures const& features);
|
||||
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||
bool collectComments = true);
|
||||
String getFormattedErrorMessages() const;
|
||||
@@ -943,7 +934,7 @@ private:
|
||||
Location extra_;
|
||||
};
|
||||
|
||||
typedef std::deque<ErrorInfo> Errors;
|
||||
using Errors = std::deque<ErrorInfo>;
|
||||
|
||||
bool readToken(Token& token);
|
||||
void skipSpaces();
|
||||
@@ -968,8 +959,7 @@ private:
|
||||
unsigned int& unicode);
|
||||
bool decodeUnicodeEscapeSequence(Token& token, Location& current,
|
||||
Location end, unsigned int& unicode);
|
||||
bool addError(const String& message, Token& token,
|
||||
Location extra = JSONCPP_NULL);
|
||||
bool addError(const String& message, Token& token, Location extra = nullptr);
|
||||
bool recoverFromError(TokenType skipUntilToken);
|
||||
bool addErrorAndRecover(const String& message, Token& token,
|
||||
TokenType skipUntilToken);
|
||||
@@ -985,38 +975,31 @@ private:
|
||||
static String normalizeEOL(Location begin, Location end);
|
||||
static bool containsNewLine(Location begin, Location end);
|
||||
|
||||
typedef std::stack<Value*> Nodes;
|
||||
using Nodes = std::stack<Value*>;
|
||||
|
||||
Nodes nodes_;
|
||||
Errors errors_;
|
||||
String document_;
|
||||
Location begin_;
|
||||
Location end_;
|
||||
Location current_;
|
||||
Location lastValueEnd_;
|
||||
Value* lastValue_;
|
||||
bool lastValueHasAComment_;
|
||||
String commentsBefore_;
|
||||
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_{};
|
||||
|
||||
OurFeatures const features_;
|
||||
bool collectComments_;
|
||||
bool collectComments_ = false;
|
||||
}; // OurReader
|
||||
|
||||
// complete copy of Read impl, for OurReader
|
||||
|
||||
bool OurReader::containsNewLine(OurReader::Location begin,
|
||||
OurReader::Location end) {
|
||||
for (; begin < end; ++begin)
|
||||
if (*begin == '\n' || *begin == '\r')
|
||||
return true;
|
||||
return false;
|
||||
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
|
||||
}
|
||||
|
||||
OurReader::OurReader(OurFeatures const& features)
|
||||
: errors_(), document_(), begin_(JSONCPP_NULL), end_(JSONCPP_NULL),
|
||||
current_(JSONCPP_NULL), lastValueEnd_(JSONCPP_NULL),
|
||||
lastValue_(JSONCPP_NULL), lastValueHasAComment_(false), commentsBefore_(),
|
||||
features_(features), collectComments_(false) {}
|
||||
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
|
||||
|
||||
bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||
bool collectComments) {
|
||||
@@ -1028,8 +1011,8 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||
end_ = endDoc;
|
||||
collectComments_ = collectComments;
|
||||
current_ = begin_;
|
||||
lastValueEnd_ = JSONCPP_NULL;
|
||||
lastValue_ = JSONCPP_NULL;
|
||||
lastValueEnd_ = nullptr;
|
||||
lastValue_ = nullptr;
|
||||
commentsBefore_.clear();
|
||||
errors_.clear();
|
||||
while (!nodes_.empty())
|
||||
@@ -1192,8 +1175,11 @@ bool OurReader::readToken(Token& token) {
|
||||
if (features_.allowSingleQuotes_) {
|
||||
token.type_ = tokenString;
|
||||
ok = readStringSingleQuote();
|
||||
break;
|
||||
} // else fall through
|
||||
} else {
|
||||
// If we don't allow single quotes, this is a failure case.
|
||||
ok = false;
|
||||
}
|
||||
break;
|
||||
case '/':
|
||||
token.type_ = tokenComment;
|
||||
ok = readComment();
|
||||
@@ -1287,7 +1273,7 @@ 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) {
|
||||
if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
|
||||
begin_ += 3;
|
||||
current_ = begin_;
|
||||
}
|
||||
@@ -1364,7 +1350,7 @@ void OurReader::addComment(Location begin, Location end,
|
||||
assert(collectComments_);
|
||||
const String& normalized = normalizeEOL(begin, end);
|
||||
if (placement == commentAfterOnSameLine) {
|
||||
assert(lastValue_ != JSONCPP_NULL);
|
||||
assert(lastValue_ != nullptr);
|
||||
lastValue_->setComment(normalized, placement);
|
||||
} else {
|
||||
commentsBefore_ += normalized;
|
||||
@@ -1580,36 +1566,32 @@ 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.
|
||||
JSONCPP_STATIC_ASSERT(LargestUInt(Value::maxLargestInt) <=
|
||||
Value::maxLargestUInt,
|
||||
"Int must be smaller than Uint");
|
||||
static_assert(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.
|
||||
JSONCPP_STATIC_ASSERT(
|
||||
Value::minLargestInt <= -Value::maxLargestInt,
|
||||
"The absolute value of minLargestInt must ve greater than or"
|
||||
"equal to maxLargestInt");
|
||||
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 / 10 >= -Value::maxLargestInt,
|
||||
"The absolute value of minLargestInt must be only 1 magnitude"
|
||||
"larger than maxLargestInt");
|
||||
|
||||
static JSONCPP_CONST Value::LargestUInt positive_threshold =
|
||||
static constexpr Value::LargestUInt positive_threshold =
|
||||
Value::maxLargestUInt / 10;
|
||||
static JSONCPP_CONST Value::UInt positive_last_digit =
|
||||
Value::maxLargestUInt % 10;
|
||||
static constexpr 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 JSONCPP_CONST Value::LargestUInt negative_threshold =
|
||||
static constexpr auto negative_threshold =
|
||||
Value::LargestUInt(-(Value::minLargestInt / 10));
|
||||
static JSONCPP_CONST Value::UInt negative_last_digit =
|
||||
static constexpr auto negative_last_digit =
|
||||
Value::UInt(-(Value::minLargestInt % 10));
|
||||
|
||||
const Value::LargestUInt threshold =
|
||||
@@ -1623,7 +1605,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
||||
if (c < '0' || c > '9')
|
||||
return decodeDouble(token, decoded);
|
||||
|
||||
const Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||
const auto digit(static_cast<Value::UInt>(c - '0'));
|
||||
if (value >= threshold) {
|
||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||
// a) we've only just touched the limit, meaing value == threshold,
|
||||
@@ -1640,7 +1622,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
||||
|
||||
if (isNegative) {
|
||||
// We use the same magnitude assumption here, just in case.
|
||||
const Value::UInt last_digit = static_cast<Value::UInt>(value % 10);
|
||||
const auto last_digit = static_cast<Value::UInt>(value % 10);
|
||||
decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
|
||||
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
|
||||
decoded = Value::LargestInt(value);
|
||||
@@ -1856,9 +1838,7 @@ String OurReader::getLocationLineAndColumn(Location location) const {
|
||||
|
||||
String OurReader::getFormattedErrorMessages() const {
|
||||
String formattedMessage;
|
||||
for (Errors::const_iterator itError = errors_.begin();
|
||||
itError != errors_.end(); ++itError) {
|
||||
const ErrorInfo& error = *itError;
|
||||
for (const auto& error : errors_) {
|
||||
formattedMessage +=
|
||||
"* " + getLocationLineAndColumn(error.token_.start_) + "\n";
|
||||
formattedMessage += " " + error.message_ + "\n";
|
||||
@@ -1871,9 +1851,7 @@ String OurReader::getFormattedErrorMessages() const {
|
||||
|
||||
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
||||
std::vector<OurReader::StructuredError> allErrors;
|
||||
for (Errors::const_iterator itError = errors_.begin();
|
||||
itError != errors_.end(); ++itError) {
|
||||
const ErrorInfo& error = *itError;
|
||||
for (const auto& error : errors_) {
|
||||
OurReader::StructuredError structured;
|
||||
structured.offset_start = error.token_.start_ - begin_;
|
||||
structured.offset_limit = error.token_.end_ - begin_;
|
||||
@@ -1891,7 +1869,7 @@ public:
|
||||
OurCharReader(bool collectComments, OurFeatures const& features)
|
||||
: collectComments_(collectComments), reader_(features) {}
|
||||
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||
String* errs) JSONCPP_OVERRIDE {
|
||||
String* errs) override {
|
||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||
if (errs) {
|
||||
*errs = reader_.getFormattedErrorMessages();
|
||||
@@ -1901,7 +1879,7 @@ public:
|
||||
};
|
||||
|
||||
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
||||
CharReaderBuilder::~CharReaderBuilder() {}
|
||||
CharReaderBuilder::~CharReaderBuilder() = default;
|
||||
CharReader* CharReaderBuilder::newCharReader() const {
|
||||
bool collectComments = settings_["collectComments"].asBool();
|
||||
OurFeatures features = OurFeatures::all();
|
||||
@@ -1922,38 +1900,34 @@ CharReader* CharReaderBuilder::newCharReader() const {
|
||||
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");
|
||||
valid_keys->insert("allowSingleQuotes");
|
||||
valid_keys->insert("stackLimit");
|
||||
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;
|
||||
if (!invalid)
|
||||
invalid = &my_invalid; // so we do not need to test for NULL
|
||||
Json::Value& inv = *invalid;
|
||||
std::set<String> valid_keys;
|
||||
getValidReaderKeys(&valid_keys);
|
||||
Value::Members keys = settings_.getMemberNames();
|
||||
size_t n = keys.size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
String const& key = keys[i];
|
||||
if (valid_keys.find(key) == valid_keys.end()) {
|
||||
inv[key] = settings_[key];
|
||||
}
|
||||
static const auto& valid_keys = *new std::set<String>{
|
||||
"collectComments",
|
||||
"allowComments",
|
||||
"allowTrailingCommas",
|
||||
"strictRoot",
|
||||
"allowDroppedNullPlaceholders",
|
||||
"allowNumericKeys",
|
||||
"allowSingleQuotes",
|
||||
"stackLimit",
|
||||
"failIfExtra",
|
||||
"rejectDupKeys",
|
||||
"allowSpecialFloats",
|
||||
"skipBom",
|
||||
};
|
||||
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
|
||||
auto key = si.name();
|
||||
if (valid_keys.count(key))
|
||||
continue;
|
||||
if (invalid)
|
||||
(*invalid)[std::move(key)] = *si;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return inv.empty();
|
||||
return invalid ? invalid->empty() : true;
|
||||
}
|
||||
|
||||
Value& CharReaderBuilder::operator[](const String& key) {
|
||||
return settings_[key];
|
||||
}
|
||||
@@ -2003,9 +1977,7 @@ 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());
|
||||
bool ret = reader->parse(begin, end, root, errs);
|
||||
delete reader;
|
||||
return ret;
|
||||
return reader->parse(begin, end, root, errs);
|
||||
}
|
||||
|
||||
IStream& operator>>(IStream& sin, Value& root) {
|
||||
|
@@ -71,7 +71,7 @@ enum {
|
||||
};
|
||||
|
||||
// Defines a char buffer for use with uintToString().
|
||||
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
||||
using UIntToStringBuffer = char[uintToStringBufferSize];
|
||||
|
||||
/** Converts an unsigned integer to string.
|
||||
* @param value Unsigned integer to convert to string
|
||||
|
@@ -48,6 +48,14 @@ 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
|
||||
@@ -110,8 +118,8 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
|
||||
if (length >= static_cast<size_t>(Value::maxInt))
|
||||
length = Value::maxInt - 1;
|
||||
|
||||
char* newString = static_cast<char*>(malloc(length + 1));
|
||||
if (newString == JSONCPP_NULL) {
|
||||
auto newString = static_cast<char*>(malloc(length + 1));
|
||||
if (newString == nullptr) {
|
||||
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
||||
"Failed to allocate string value buffer");
|
||||
}
|
||||
@@ -131,8 +139,8 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
|
||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||
"length too big for prefixing");
|
||||
size_t actualLength = sizeof(length) + length + 1;
|
||||
char* newString = static_cast<char*>(malloc(actualLength));
|
||||
if (newString == JSONCPP_NULL) {
|
||||
auto newString = static_cast<char*>(malloc(actualLength));
|
||||
if (newString == nullptr) {
|
||||
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
||||
"Failed to allocate string value buffer");
|
||||
}
|
||||
@@ -192,9 +200,9 @@ static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
||||
namespace Json {
|
||||
|
||||
#if JSON_USE_EXCEPTION
|
||||
Exception::Exception(String msg) : msg_(JSONCPP_MOVE(msg)) {}
|
||||
Exception::~Exception() JSONCPP_NOEXCEPT {}
|
||||
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
|
||||
Exception::Exception(String msg) : msg_(std::move(msg)) {}
|
||||
Exception::~Exception() noexcept = default;
|
||||
char const* Exception::what() const noexcept { return msg_.c_str(); }
|
||||
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
||||
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
||||
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
||||
@@ -225,8 +233,7 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
||||
// Notes: policy_ indicates if the string was allocated when
|
||||
// a string is stored.
|
||||
|
||||
Value::CZString::CZString(ArrayIndex index)
|
||||
: cstr_(JSONCPP_NULL), index_(index) {}
|
||||
Value::CZString::CZString(ArrayIndex index) : cstr_(nullptr), index_(index) {}
|
||||
|
||||
Value::CZString::CZString(char const* str, unsigned length,
|
||||
DuplicationPolicy allocate)
|
||||
@@ -237,10 +244,9 @@ Value::CZString::CZString(char const* str, unsigned length,
|
||||
}
|
||||
|
||||
Value::CZString::CZString(const CZString& other) {
|
||||
cstr_ =
|
||||
(other.storage_.policy_ != noDuplication && other.cstr_ != JSONCPP_NULL
|
||||
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
||||
: other.cstr_);
|
||||
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != nullptr
|
||||
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
||||
: other.cstr_);
|
||||
storage_.policy_ =
|
||||
static_cast<unsigned>(
|
||||
other.cstr_
|
||||
@@ -252,12 +258,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_ = JSONCPP_NULL;
|
||||
other.cstr_ = nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
Value::CZString::~CZString() {
|
||||
if (cstr_ && storage_.policy_ == duplicate) {
|
||||
releaseStringValue(const_cast<char*>(cstr_),
|
||||
@@ -278,14 +284,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_ = JSONCPP_NULL;
|
||||
other.cstr_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Value::CZString::operator<(const CZString& other) const {
|
||||
if (!cstr_)
|
||||
return index_ < other.index_;
|
||||
@@ -394,7 +400,7 @@ Value::Value(double value) {
|
||||
|
||||
Value::Value(const char* value) {
|
||||
initBasic(stringValue, true);
|
||||
JSON_ASSERT_MESSAGE(value != JSONCPP_NULL,
|
||||
JSON_ASSERT_MESSAGE(value != nullptr,
|
||||
"Null Value Passed to Value Constructor");
|
||||
value_.string_ = duplicateAndPrefixStringValue(
|
||||
value, static_cast<unsigned>(strlen(value)));
|
||||
@@ -426,12 +432,11 @@ 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();
|
||||
@@ -442,12 +447,11 @@ 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_);
|
||||
@@ -499,9 +503,8 @@ bool Value::operator<(const Value& other) const {
|
||||
case booleanValue:
|
||||
return value_.bool_ < other.value_.bool_;
|
||||
case stringValue: {
|
||||
if ((value_.string_ == JSONCPP_NULL) ||
|
||||
(other.value_.string_ == JSONCPP_NULL)) {
|
||||
return other.value_.string_ != JSONCPP_NULL;
|
||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
||||
return other.value_.string_ != nullptr;
|
||||
}
|
||||
unsigned this_len;
|
||||
unsigned other_len;
|
||||
@@ -522,8 +525,8 @@ bool Value::operator<(const Value& other) const {
|
||||
}
|
||||
case arrayValue:
|
||||
case objectValue: {
|
||||
long unsigned int thisSize = value_.map_->size();
|
||||
long unsigned int otherSize = other.value_.map_->size();
|
||||
auto thisSize = value_.map_->size();
|
||||
auto otherSize = other.value_.map_->size();
|
||||
if (thisSize != otherSize)
|
||||
return thisSize < otherSize;
|
||||
return (*value_.map_) < (*other.value_.map_);
|
||||
@@ -555,8 +558,7 @@ bool Value::operator==(const Value& other) const {
|
||||
case booleanValue:
|
||||
return value_.bool_ == other.value_.bool_;
|
||||
case stringValue: {
|
||||
if ((value_.string_ == JSONCPP_NULL) ||
|
||||
(other.value_.string_ == JSONCPP_NULL)) {
|
||||
if ((value_.string_ == nullptr) || (other.value_.string_ == nullptr)) {
|
||||
return (value_.string_ == other.value_.string_);
|
||||
}
|
||||
unsigned this_len;
|
||||
@@ -588,8 +590,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_ == JSONCPP_NULL)
|
||||
return JSONCPP_NULL;
|
||||
if (value_.string_ == nullptr)
|
||||
return nullptr;
|
||||
unsigned this_len;
|
||||
char const* this_str;
|
||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &this_len,
|
||||
@@ -614,7 +616,7 @@ unsigned Value::getCStringLength() const {
|
||||
bool Value::getString(char const** begin, char const** end) const {
|
||||
if (type() != stringValue)
|
||||
return false;
|
||||
if (value_.string_ == JSONCPP_NULL)
|
||||
if (value_.string_ == nullptr)
|
||||
return false;
|
||||
unsigned length;
|
||||
decodePrefixedString(this->isAllocated(), this->value_.string_, &length,
|
||||
@@ -628,7 +630,7 @@ String Value::asString() const {
|
||||
case nullValue:
|
||||
return "";
|
||||
case stringValue: {
|
||||
if (value_.string_ == JSONCPP_NULL)
|
||||
if (value_.string_ == nullptr)
|
||||
return "";
|
||||
unsigned this_len;
|
||||
char const* this_str;
|
||||
@@ -811,7 +813,7 @@ bool Value::asBool() const {
|
||||
return value_.uint_ != 0;
|
||||
case realValue: {
|
||||
// According to JavaScript language zero or NaN is regarded as false
|
||||
const int value_classification = std::fpclassify(value_.real_);
|
||||
const auto value_classification = std::fpclassify(value_.real_);
|
||||
return value_classification != FP_ZERO && value_classification != FP_NAN;
|
||||
}
|
||||
default:
|
||||
@@ -926,7 +928,7 @@ Value& Value::operator[](ArrayIndex index) {
|
||||
if (type() == nullValue)
|
||||
*this = Value(arrayValue);
|
||||
CZString key(index);
|
||||
ObjectValues::iterator it = value_.map_->lower_bound(key);
|
||||
auto it = value_.map_->lower_bound(key);
|
||||
if (it != value_.map_->end() && (*it).first == key)
|
||||
return (*it).second;
|
||||
|
||||
@@ -965,7 +967,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;
|
||||
}
|
||||
@@ -1040,7 +1042,7 @@ Value& Value::resolveReference(const char* key) {
|
||||
*this = Value(objectValue);
|
||||
CZString actualKey(key, static_cast<unsigned>(strlen(key)),
|
||||
CZString::noDuplication); // NOTE!
|
||||
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||
auto it = value_.map_->lower_bound(actualKey);
|
||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||
return (*it).second;
|
||||
|
||||
@@ -1059,7 +1061,7 @@ Value& Value::resolveReference(char const* key, char const* end) {
|
||||
*this = Value(objectValue);
|
||||
CZString actualKey(key, static_cast<unsigned>(end - key),
|
||||
CZString::duplicateOnCopy);
|
||||
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||
auto it = value_.map_->lower_bound(actualKey);
|
||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||
return (*it).second;
|
||||
|
||||
@@ -1081,12 +1083,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 JSONCPP_NULL;
|
||||
return nullptr;
|
||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||
CZString::noDuplication);
|
||||
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
||||
if (it == value_.map_->end())
|
||||
return JSONCPP_NULL;
|
||||
return nullptr;
|
||||
return &(*it).second;
|
||||
}
|
||||
Value* Value::demand(char const* begin, char const* end) {
|
||||
@@ -1120,8 +1122,8 @@ Value& Value::operator[](const StaticString& key) {
|
||||
return resolveReference(key.c_str());
|
||||
}
|
||||
|
||||
#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");
|
||||
@@ -1130,19 +1132,12 @@ 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
|
||||
|
||||
#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();
|
||||
@@ -1150,11 +1145,12 @@ bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||
return false;
|
||||
}
|
||||
for (ArrayIndex i = length; i > index; i--) {
|
||||
(*this)[i] = JSONCPP_MOVE((*this)[i - 1]);
|
||||
(*this)[i] = std::move((*this)[i - 1]);
|
||||
}
|
||||
(*this)[index] = JSONCPP_MOVE(newValue);
|
||||
(*this)[index] = std::move(newValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
Value Value::get(char const* begin, char const* end,
|
||||
Value const& defaultValue) const {
|
||||
Value const* found = find(begin, end);
|
||||
@@ -1173,11 +1169,11 @@ bool Value::removeMember(const char* begin, const char* end, Value* removed) {
|
||||
}
|
||||
CZString actualKey(begin, static_cast<unsigned>(end - begin),
|
||||
CZString::noDuplication);
|
||||
ObjectValues::iterator it = value_.map_->find(actualKey);
|
||||
auto it = value_.map_->find(actualKey);
|
||||
if (it == value_.map_->end())
|
||||
return false;
|
||||
if (removed)
|
||||
*removed = JSONCPP_MOVE(it->second);
|
||||
*removed = std::move(it->second);
|
||||
value_.map_->erase(it);
|
||||
return true;
|
||||
}
|
||||
@@ -1203,7 +1199,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
||||
return false;
|
||||
}
|
||||
CZString key(index);
|
||||
ObjectValues::iterator it = value_.map_->find(key);
|
||||
auto it = value_.map_->find(key);
|
||||
if (it == value_.map_->end()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1217,14 +1213,14 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
||||
}
|
||||
// erase the last one ("leftover")
|
||||
CZString keyLast(oldSize - 1);
|
||||
ObjectValues::iterator itLast = value_.map_->find(keyLast);
|
||||
auto itLast = value_.map_->find(keyLast);
|
||||
value_.map_->erase(itLast);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Value::isMember(char const* begin, char const* end) const {
|
||||
Value const* value = find(begin, end);
|
||||
return JSONCPP_NULL != value;
|
||||
return nullptr != value;
|
||||
}
|
||||
bool Value::isMember(char const* key) const {
|
||||
return isMember(key, key + strlen(key));
|
||||
@@ -1374,44 +1370,53 @@ bool Value::isArray() const { return type() == arrayValue; }
|
||||
|
||||
bool Value::isObject() const { return type() == objectValue; }
|
||||
|
||||
Value::Comments::Comments(const Comments& that) {
|
||||
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||
ptr_[i] = that.ptr_[i];
|
||||
}
|
||||
}
|
||||
Value::Comments::Comments(const Comments& that)
|
||||
: ptr_{cloneUnique(that.ptr_)} {}
|
||||
|
||||
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
|
||||
|
||||
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
||||
for (size_t i = 0; i < numberOfCommentPlacement; i++) {
|
||||
ptr_[i] = that.ptr_[i];
|
||||
}
|
||||
ptr_ = cloneUnique(that.ptr_);
|
||||
return *this;
|
||||
}
|
||||
bool Value::Comments::has(CommentPlacement slot) const {
|
||||
return !ptr_[slot].empty();
|
||||
|
||||
Value::Comments& Value::Comments::operator=(Comments&& that) {
|
||||
ptr_ = std::move(that.ptr_);
|
||||
return *this;
|
||||
}
|
||||
|
||||
String Value::Comments::get(CommentPlacement slot) const { return ptr_[slot]; }
|
||||
bool Value::Comments::has(CommentPlacement slot) const {
|
||||
return ptr_ && !(*ptr_)[slot].empty();
|
||||
}
|
||||
|
||||
String Value::Comments::get(CommentPlacement slot) const {
|
||||
if (!ptr_)
|
||||
return {};
|
||||
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 < numberOfCommentPlacement) {
|
||||
ptr_[slot] = comment;
|
||||
if (slot < CommentPlacement::numberOfCommentPlacement) {
|
||||
(*ptr_)[slot] = std::move(comment);
|
||||
}
|
||||
}
|
||||
|
||||
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')) {
|
||||
void Value::setComment(String comment, CommentPlacement placement) {
|
||||
if (!comment.empty() && (comment.back() == '\n')) {
|
||||
// Always discard trailing newline, to aid indentation.
|
||||
len -= 1;
|
||||
comment.pop_back();
|
||||
}
|
||||
comments_.set(placement, String(comment, len));
|
||||
}
|
||||
void Value::setComment(const String& comment, CommentPlacement placement) {
|
||||
setComment(comment.c_str(), comment.length(), placement);
|
||||
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));
|
||||
}
|
||||
|
||||
bool Value::hasComment(CommentPlacement placement) const {
|
||||
return comments_.has(placement);
|
||||
}
|
||||
@@ -1448,7 +1453,7 @@ Value::const_iterator Value::begin() const {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return const_iterator();
|
||||
return {};
|
||||
}
|
||||
|
||||
Value::const_iterator Value::end() const {
|
||||
@@ -1461,7 +1466,7 @@ Value::const_iterator Value::end() const {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return const_iterator();
|
||||
return {};
|
||||
}
|
||||
|
||||
Value::iterator Value::begin() {
|
||||
@@ -1493,15 +1498,14 @@ Value::iterator Value::end() {
|
||||
// class PathArgument
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
PathArgument::PathArgument() {}
|
||||
PathArgument::PathArgument() = default;
|
||||
|
||||
PathArgument::PathArgument(ArrayIndex index)
|
||||
: index_(index), kind_(kindIndex) {}
|
||||
|
||||
PathArgument::PathArgument(const char* key) : key_(key), kind_(kindKey) {}
|
||||
|
||||
PathArgument::PathArgument(String key)
|
||||
: key_(JSONCPP_MOVE(key)), kind_(kindKey) {}
|
||||
PathArgument::PathArgument(String key) : key_(std::move(key)), kind_(kindKey) {}
|
||||
|
||||
// class Path
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
@@ -1522,7 +1526,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();
|
||||
InArgs::const_iterator itInArg = in.begin();
|
||||
auto itInArg = in.begin();
|
||||
while (current != end) {
|
||||
if (*current == '[') {
|
||||
++current;
|
||||
@@ -1568,9 +1572,7 @@ void Path::invalidPath(const String& /*path*/, int /*location*/) {
|
||||
|
||||
const Value& Path::resolve(const Value& root) const {
|
||||
const Value* node = &root;
|
||||
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||
++itArg) {
|
||||
const PathArgument& arg = *itArg;
|
||||
for (const auto& arg : args_) {
|
||||
if (arg.kind_ == PathArgument::kindIndex) {
|
||||
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
||||
// Error: unable to resolve path (array value expected at position... )
|
||||
@@ -1595,9 +1597,7 @@ const Value& Path::resolve(const Value& root) const {
|
||||
|
||||
Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
||||
const Value* node = &root;
|
||||
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||
++itArg) {
|
||||
const PathArgument& arg = *itArg;
|
||||
for (const auto& arg : args_) {
|
||||
if (arg.kind_ == PathArgument::kindIndex) {
|
||||
if (!node->isArray() || !node->isValidIndex(arg.index_))
|
||||
return defaultValue;
|
||||
@@ -1615,9 +1615,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
||||
|
||||
Value& Path::make(Value& root) const {
|
||||
Value* node = &root;
|
||||
for (Args::const_iterator itArg = args_.begin(); itArg != args_.end();
|
||||
++itArg) {
|
||||
const PathArgument& arg = *itArg;
|
||||
for (const auto& arg : args_) {
|
||||
if (arg.kind_ == PathArgument::kindIndex) {
|
||||
if (!node->isArray()) {
|
||||
// Error: node is not an array at position ...
|
||||
|
@@ -15,7 +15,7 @@ namespace Json {
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase() : current_(), isNull_(true) {}
|
||||
ValueIteratorBase::ValueIteratorBase() : current_() {}
|
||||
|
||||
ValueIteratorBase::ValueIteratorBase(
|
||||
const Value::ObjectValues::iterator& current)
|
||||
@@ -98,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 = JSONCPP_NULL;
|
||||
return JSONCPP_NULL;
|
||||
*end = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
*end = cname + (*current_).first.length();
|
||||
return cname;
|
||||
@@ -113,7 +113,7 @@ char const* ValueIteratorBase::memberName(char const** end) const {
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueConstIterator::ValueConstIterator() {}
|
||||
ValueConstIterator::ValueConstIterator() = default;
|
||||
|
||||
ValueConstIterator::ValueConstIterator(
|
||||
const Value::ObjectValues::iterator& current)
|
||||
@@ -136,7 +136,7 @@ operator=(const ValueIteratorBase& other) {
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
ValueIterator::ValueIterator() {}
|
||||
ValueIterator::ValueIterator() = default;
|
||||
|
||||
ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
||||
: ValueIteratorBase(current) {}
|
||||
@@ -146,8 +146,7 @@ ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||
}
|
||||
|
||||
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||
: ValueIteratorBase(other) {}
|
||||
ValueIterator::ValueIterator(const ValueIterator& other) = default;
|
||||
|
||||
ValueIterator& ValueIterator::operator=(const SelfType& other) {
|
||||
copy(other);
|
||||
|
@@ -7,7 +7,9 @@
|
||||
#include "json_tool.h"
|
||||
#include <json/writer.h>
|
||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstring>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
@@ -83,7 +85,11 @@
|
||||
|
||||
namespace Json {
|
||||
|
||||
typedef StreamWriter* StreamWriterPtr;
|
||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
||||
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
||||
#else
|
||||
using StreamWriterPtr = std::auto_ptr<StreamWriter>;
|
||||
#endif
|
||||
|
||||
String valueToString(LargestInt value) {
|
||||
UIntToStringBuffer buffer;
|
||||
@@ -132,12 +138,12 @@ String valueToString(double value, bool useSpecialFloats,
|
||||
|
||||
String buffer(size_t(36), '\0');
|
||||
while (true) {
|
||||
int len =
|
||||
jsoncpp_snprintf(&*buffer.begin(), buffer.size(),
|
||||
(precisionType == significantDigits) ? "%.*g" : "%.*f",
|
||||
precision, value);
|
||||
int len = jsoncpp_snprintf(
|
||||
&*buffer.begin(), buffer.size(),
|
||||
(precisionType == PrecisionType::significantDigits) ? "%.*g" : "%.*f",
|
||||
precision, value);
|
||||
assert(len >= 0);
|
||||
size_t wouldPrint = static_cast<size_t>(len);
|
||||
auto wouldPrint = static_cast<size_t>(len);
|
||||
if (wouldPrint >= buffer.size()) {
|
||||
buffer.resize(wouldPrint + 1);
|
||||
continue;
|
||||
@@ -149,7 +155,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 == decimalPlaces) {
|
||||
if (precisionType == PrecisionType::decimalPlaces) {
|
||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
||||
}
|
||||
|
||||
@@ -169,17 +175,12 @@ String valueToString(double value, unsigned int precision,
|
||||
|
||||
String valueToString(bool value) { return value ? "true" : "false"; }
|
||||
|
||||
static bool isAnyCharRequiredQuoting(char const* s, size_t n) {
|
||||
static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
|
||||
assert(s || !n);
|
||||
|
||||
char const* const end = s + n;
|
||||
for (char const* cur = s; cur < end; ++cur) {
|
||||
if (*cur == '\\' || *cur == '\"' ||
|
||||
static_cast<unsigned char>(*cur) < ' ' ||
|
||||
static_cast<unsigned char>(*cur) >= 0x80)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return std::any_of(s, s + n, [](unsigned char c) {
|
||||
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
|
||||
});
|
||||
}
|
||||
|
||||
static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
|
||||
@@ -261,12 +262,20 @@ static String toHex16Bit(unsigned int x) {
|
||||
return result;
|
||||
}
|
||||
|
||||
static void appendRaw(String& result, unsigned ch) {
|
||||
result += static_cast<char>(ch);
|
||||
}
|
||||
|
||||
static void appendHex(String& result, unsigned ch) {
|
||||
result.append("\\u").append(toHex16Bit(ch));
|
||||
}
|
||||
|
||||
static String valueToQuotedStringN(const char* value, unsigned length,
|
||||
bool emitUTF8 = false) {
|
||||
if (value == JSONCPP_NULL)
|
||||
if (value == nullptr)
|
||||
return "";
|
||||
|
||||
if (!isAnyCharRequiredQuoting(value, length))
|
||||
if (!doesAnyCharRequireEscaping(value, length))
|
||||
return String("\"") + value + "\"";
|
||||
// We have to walk value and escape any special characters.
|
||||
// Appending to String is not efficient, but this should be rare.
|
||||
@@ -309,29 +318,26 @@ static String valueToQuotedStringN(const char* value, unsigned length,
|
||||
// sequence from occurring.
|
||||
default: {
|
||||
if (emitUTF8) {
|
||||
result += *c;
|
||||
unsigned codepoint = static_cast<unsigned char>(*c);
|
||||
if (codepoint < 0x20) {
|
||||
appendHex(result, codepoint);
|
||||
} else {
|
||||
appendRaw(result, codepoint);
|
||||
}
|
||||
} else {
|
||||
unsigned int codepoint = utf8ToCodepoint(c, end);
|
||||
const unsigned int FIRST_NON_CONTROL_CODEPOINT = 0x20;
|
||||
const unsigned int LAST_NON_CONTROL_CODEPOINT = 0x7F;
|
||||
const unsigned int FIRST_SURROGATE_PAIR_CODEPOINT = 0x10000;
|
||||
// don't escape non-control characters
|
||||
// (short escape sequence are applied above)
|
||||
if (FIRST_NON_CONTROL_CODEPOINT <= codepoint &&
|
||||
codepoint <= LAST_NON_CONTROL_CODEPOINT) {
|
||||
result += static_cast<char>(codepoint);
|
||||
} else if (codepoint <
|
||||
FIRST_SURROGATE_PAIR_CODEPOINT) { // codepoint is in Basic
|
||||
// Multilingual Plane
|
||||
result += "\\u";
|
||||
result += toHex16Bit(codepoint);
|
||||
} else { // codepoint is not in Basic Multilingual Plane
|
||||
// convert to surrogate pair first
|
||||
codepoint -= FIRST_SURROGATE_PAIR_CODEPOINT;
|
||||
result += "\\u";
|
||||
result += toHex16Bit((codepoint >> 10) + 0xD800);
|
||||
result += "\\u";
|
||||
result += toHex16Bit((codepoint & 0x3FF) + 0xDC00);
|
||||
unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
|
||||
if (codepoint < 0x20) {
|
||||
appendHex(result, codepoint);
|
||||
} else if (codepoint < 0x80) {
|
||||
appendRaw(result, codepoint);
|
||||
} else if (codepoint < 0x10000) {
|
||||
// Basic Multilingual Plane
|
||||
appendHex(result, codepoint);
|
||||
} else {
|
||||
// Extended Unicode. Encode 20 bits as a surrogate pair.
|
||||
codepoint -= 0x10000;
|
||||
appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
|
||||
appendHex(result, 0xdc00 + (codepoint & 0x3ff));
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -347,14 +353,14 @@ String valueToQuotedString(const char* value) {
|
||||
|
||||
// Class Writer
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
Writer::~Writer() {}
|
||||
Writer::~Writer() = default;
|
||||
|
||||
// Class FastWriter
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
FastWriter::FastWriter()
|
||||
: yamlCompatibilityEnabled_(false), dropNullPlaceholders_(false),
|
||||
omitEndingLineFeed_(false) {}
|
||||
|
||||
= default;
|
||||
|
||||
void FastWriter::enableYAMLCompatibility() { yamlCompatibilityEnabled_ = true; }
|
||||
|
||||
@@ -410,8 +416,7 @@ void FastWriter::writeValue(const Value& value) {
|
||||
case objectValue: {
|
||||
Value::Members members(value.getMemberNames());
|
||||
document_ += '{';
|
||||
for (Value::Members::const_iterator it = members.begin();
|
||||
it != members.end(); ++it) {
|
||||
for (auto it = members.begin(); it != members.end(); ++it) {
|
||||
const String& name = *it;
|
||||
if (it != members.begin())
|
||||
document_ += ',';
|
||||
@@ -428,8 +433,7 @@ void FastWriter::writeValue(const Value& value) {
|
||||
// Class StyledWriter
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
StyledWriter::StyledWriter()
|
||||
: rightMargin_(74), indentSize_(3), addChildValues_() {}
|
||||
StyledWriter::StyledWriter() = default;
|
||||
|
||||
String StyledWriter::write(const Value& root) {
|
||||
document_.clear();
|
||||
@@ -480,7 +484,7 @@ void StyledWriter::writeValue(const Value& value) {
|
||||
else {
|
||||
writeWithIndent("{");
|
||||
indent();
|
||||
Value::Members::const_iterator it = members.begin();
|
||||
auto it = members.begin();
|
||||
for (;;) {
|
||||
const String& name = *it;
|
||||
const Value& childValue = value[name];
|
||||
@@ -642,9 +646,8 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
StyledStreamWriter::StyledStreamWriter(String indentation)
|
||||
: document_(JSONCPP_NULL), rightMargin_(74),
|
||||
indentation_(JSONCPP_MOVE(indentation)), addChildValues_(),
|
||||
indented_(false) {}
|
||||
: document_(nullptr), indentation_(std::move(indentation)),
|
||||
addChildValues_(), indented_(false) {}
|
||||
|
||||
void StyledStreamWriter::write(OStream& out, const Value& root) {
|
||||
document_ = &out;
|
||||
@@ -658,7 +661,7 @@ void StyledStreamWriter::write(OStream& out, const Value& root) {
|
||||
writeValue(root);
|
||||
writeCommentAfterValueOnSameLine(root);
|
||||
*document_ << "\n";
|
||||
document_ = JSONCPP_NULL; // Forget the stream, for safety.
|
||||
document_ = nullptr; // Forget the stream, for safety.
|
||||
}
|
||||
|
||||
void StyledStreamWriter::writeValue(const Value& value) {
|
||||
@@ -699,7 +702,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
||||
else {
|
||||
writeWithIndent("{");
|
||||
indent();
|
||||
Value::Members::const_iterator it = members.begin();
|
||||
auto it = members.begin();
|
||||
for (;;) {
|
||||
const String& name = *it;
|
||||
const Value& childValue = value[name];
|
||||
@@ -877,7 +880,7 @@ struct BuiltStyledStreamWriter : public StreamWriter {
|
||||
String endingLineFeedSymbol, bool useSpecialFloats,
|
||||
bool emitUTF8, unsigned int precision,
|
||||
PrecisionType precisionType);
|
||||
int write(Value const& root, OStream* sout) JSONCPP_OVERRIDE;
|
||||
int write(Value const& root, OStream* sout) override;
|
||||
|
||||
private:
|
||||
void writeValue(Value const& value);
|
||||
@@ -892,7 +895,7 @@ private:
|
||||
void writeCommentAfterValueOnSameLine(Value const& root);
|
||||
static bool hasCommentForValue(const Value& value);
|
||||
|
||||
typedef std::vector<String> ChildValues;
|
||||
using ChildValues = std::vector<String>;
|
||||
|
||||
ChildValues childValues_;
|
||||
String indentString_;
|
||||
@@ -913,10 +916,9 @@ 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_(JSONCPP_MOVE(indentation)), cs_(cs),
|
||||
colonSymbol_(JSONCPP_MOVE(colonSymbol)),
|
||||
nullSymbol_(JSONCPP_MOVE(nullSymbol)),
|
||||
endingLineFeedSymbol_(JSONCPP_MOVE(endingLineFeedSymbol)),
|
||||
: rightMargin_(74), indentation_(std::move(indentation)), cs_(cs),
|
||||
colonSymbol_(std::move(colonSymbol)), nullSymbol_(std::move(nullSymbol)),
|
||||
endingLineFeedSymbol_(std::move(endingLineFeedSymbol)),
|
||||
addChildValues_(false), indented_(false),
|
||||
useSpecialFloats_(useSpecialFloats), emitUTF8_(emitUTF8),
|
||||
precision_(precision), precisionType_(precisionType) {}
|
||||
@@ -932,7 +934,7 @@ int BuiltStyledStreamWriter::write(Value const& root, OStream* sout) {
|
||||
writeValue(root);
|
||||
writeCommentAfterValueOnSameLine(root);
|
||||
*sout_ << endingLineFeedSymbol_;
|
||||
sout_ = JSONCPP_NULL;
|
||||
sout_ = nullptr;
|
||||
return 0;
|
||||
}
|
||||
void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
@@ -975,7 +977,7 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
||||
else {
|
||||
writeWithIndent("{");
|
||||
indent();
|
||||
Value::Members::const_iterator it = members.begin();
|
||||
auto it = members.begin();
|
||||
for (;;) {
|
||||
String const& name = *it;
|
||||
Value const& childValue = value[name];
|
||||
@@ -1151,11 +1153,11 @@ bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
|
||||
///////////////
|
||||
// StreamWriter
|
||||
|
||||
StreamWriter::StreamWriter() : sout_(JSONCPP_NULL) {}
|
||||
StreamWriter::~StreamWriter() {}
|
||||
StreamWriter::Factory::~Factory() {}
|
||||
StreamWriter::StreamWriter() : sout_(nullptr) {}
|
||||
StreamWriter::~StreamWriter() = default;
|
||||
StreamWriter::Factory::~Factory() = default;
|
||||
StreamWriterBuilder::StreamWriterBuilder() { setDefaults(&settings_); }
|
||||
StreamWriterBuilder::~StreamWriterBuilder() {}
|
||||
StreamWriterBuilder::~StreamWriterBuilder() = default;
|
||||
StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
||||
const String indentation = settings_["indentation"].asString();
|
||||
const String cs_str = settings_["commentStyle"].asString();
|
||||
@@ -1175,9 +1177,9 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
||||
}
|
||||
PrecisionType precisionType(significantDigits);
|
||||
if (pt_str == "significant") {
|
||||
precisionType = significantDigits;
|
||||
precisionType = PrecisionType::significantDigits;
|
||||
} else if (pt_str == "decimal") {
|
||||
precisionType = decimalPlaces;
|
||||
precisionType = PrecisionType::decimalPlaces;
|
||||
} else {
|
||||
throwRuntimeError("precisionType must be 'significant' or 'decimal'");
|
||||
}
|
||||
@@ -1198,34 +1200,30 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
||||
endingLineFeedSymbol, usf, emitUTF8, pre,
|
||||
precisionType);
|
||||
}
|
||||
static void getValidWriterKeys(std::set<String>* valid_keys) {
|
||||
valid_keys->clear();
|
||||
valid_keys->insert("indentation");
|
||||
valid_keys->insert("commentStyle");
|
||||
valid_keys->insert("enableYAMLCompatibility");
|
||||
valid_keys->insert("dropNullPlaceholders");
|
||||
valid_keys->insert("useSpecialFloats");
|
||||
valid_keys->insert("emitUTF8");
|
||||
valid_keys->insert("precision");
|
||||
valid_keys->insert("precisionType");
|
||||
}
|
||||
|
||||
bool StreamWriterBuilder::validate(Json::Value* invalid) const {
|
||||
Json::Value my_invalid;
|
||||
if (!invalid)
|
||||
invalid = &my_invalid; // so we do not need to test for NULL
|
||||
Json::Value& inv = *invalid;
|
||||
std::set<String> valid_keys;
|
||||
getValidWriterKeys(&valid_keys);
|
||||
Value::Members keys = settings_.getMemberNames();
|
||||
size_t n = keys.size();
|
||||
for (size_t i = 0; i < n; ++i) {
|
||||
String const& key = keys[i];
|
||||
if (valid_keys.find(key) == valid_keys.end()) {
|
||||
inv[key] = settings_[key];
|
||||
}
|
||||
static const auto& valid_keys = *new std::set<String>{
|
||||
"indentation",
|
||||
"commentStyle",
|
||||
"enableYAMLCompatibility",
|
||||
"dropNullPlaceholders",
|
||||
"useSpecialFloats",
|
||||
"emitUTF8",
|
||||
"precision",
|
||||
"precisionType",
|
||||
};
|
||||
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
|
||||
auto key = si.name();
|
||||
if (valid_keys.count(key))
|
||||
continue;
|
||||
if (invalid)
|
||||
(*invalid)[std::move(key)] = *si;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
return inv.empty();
|
||||
return invalid ? invalid->empty() : true;
|
||||
}
|
||||
|
||||
Value& StreamWriterBuilder::operator[](const String& key) {
|
||||
return settings_[key];
|
||||
}
|
||||
@@ -1247,7 +1245,6 @@ 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();
|
||||
}
|
||||
|
||||
@@ -1255,7 +1252,6 @@ OStream& operator<<(OStream& sout, Value const& root) {
|
||||
StreamWriterBuilder builder;
|
||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||
writer->write(root, &sout);
|
||||
delete writer;
|
||||
return sout;
|
||||
}
|
||||
|
||||
|
@@ -15,8 +15,10 @@ if(BUILD_SHARED_LIBS)
|
||||
else()
|
||||
add_definitions( -DJSON_DLL )
|
||||
endif()
|
||||
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
||||
else()
|
||||
target_link_libraries(jsoncpp_test jsoncpp_static)
|
||||
endif()
|
||||
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
||||
|
||||
# another way to solve issue #90
|
||||
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
|
||||
|
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "fuzz.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <json/config.h>
|
||||
#include <json/json.h>
|
||||
#include <memory>
|
||||
@@ -40,14 +41,14 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
||||
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
||||
|
||||
Json::CharReader* reader(builder.newCharReader());
|
||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||
|
||||
Json::Value root;
|
||||
const char* data_str = reinterpret_cast<const char*>(data);
|
||||
const auto data_str = reinterpret_cast<const char*>(data);
|
||||
try {
|
||||
reader->parse(data_str, data_str + size, &root, JSONCPP_NULL);
|
||||
reader->parse(data_str, data_str + size, &root, nullptr);
|
||||
} catch (Json::Exception const&) {
|
||||
}
|
||||
delete reader;
|
||||
// Whether it succeeded or not doesn't matter.
|
||||
return 0;
|
||||
}
|
||||
|
@@ -73,11 +73,10 @@ namespace JsonTest {
|
||||
// class TestResult
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
TestResult::TestResult()
|
||||
: predicateId_(1), lastUsedPredicateId_(0), messageTarget_(JSONCPP_NULL) {
|
||||
TestResult::TestResult() {
|
||||
// The root predicate has id 0
|
||||
rootPredicateNode_.id_ = 0;
|
||||
rootPredicateNode_.next_ = JSONCPP_NULL;
|
||||
rootPredicateNode_.next_ = nullptr;
|
||||
predicateStackTail_ = &rootPredicateNode_;
|
||||
}
|
||||
|
||||
@@ -89,7 +88,7 @@ TestResult& TestResult::addFailure(const char* file, unsigned int line,
|
||||
/// added.
|
||||
unsigned int nestingLevel = 0;
|
||||
PredicateContext* lastNode = rootPredicateNode_.next_;
|
||||
for (; lastNode != JSONCPP_NULL; lastNode = lastNode->next_) {
|
||||
for (; lastNode != nullptr; lastNode = lastNode->next_) {
|
||||
if (lastNode->id_ > lastUsedPredicateId_) // new PredicateContext
|
||||
{
|
||||
lastUsedPredicateId_ = lastNode->id_;
|
||||
@@ -122,18 +121,17 @@ void TestResult::addFailureInfo(const char* file, unsigned int line,
|
||||
|
||||
TestResult& TestResult::popPredicateContext() {
|
||||
PredicateContext* lastNode = &rootPredicateNode_;
|
||||
while (lastNode->next_ != JSONCPP_NULL &&
|
||||
lastNode->next_->next_ != JSONCPP_NULL) {
|
||||
while (lastNode->next_ != nullptr && lastNode->next_->next_ != nullptr) {
|
||||
lastNode = lastNode->next_;
|
||||
}
|
||||
// Set message target to popped failure
|
||||
PredicateContext* tail = lastNode->next_;
|
||||
if (tail != JSONCPP_NULL && tail->failure_ != JSONCPP_NULL) {
|
||||
if (tail != nullptr && tail->failure_ != nullptr) {
|
||||
messageTarget_ = tail->failure_;
|
||||
}
|
||||
// Remove tail from list
|
||||
predicateStackTail_ = lastNode;
|
||||
lastNode->next_ = JSONCPP_NULL;
|
||||
lastNode->next_ = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -149,9 +147,7 @@ void TestResult::printFailure(bool printTestName) const {
|
||||
}
|
||||
|
||||
// Print in reverse to display the callstack in the right order
|
||||
for (Failures::const_iterator it = failures_.begin(); it != failures_.end();
|
||||
++it) {
|
||||
const Failure& failure = *it;
|
||||
for (const auto& failure : failures_) {
|
||||
Json::String indent(failure.nestingLevel_ * 2, ' ');
|
||||
if (failure.file_) {
|
||||
printf("%s%s(%u): ", indent.c_str(), failure.file_, failure.line_);
|
||||
@@ -185,7 +181,7 @@ Json::String TestResult::indentText(const Json::String& text,
|
||||
}
|
||||
|
||||
TestResult& TestResult::addToLastFailure(const Json::String& message) {
|
||||
if (messageTarget_ != JSONCPP_NULL) {
|
||||
if (messageTarget_ != nullptr) {
|
||||
messageTarget_->message_ += message;
|
||||
}
|
||||
return *this;
|
||||
@@ -206,9 +202,9 @@ TestResult& TestResult::operator<<(bool value) {
|
||||
// class TestCase
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
TestCase::TestCase() : result_(JSONCPP_NULL) {}
|
||||
TestCase::TestCase() = default;
|
||||
|
||||
TestCase::~TestCase() {}
|
||||
TestCase::~TestCase() = default;
|
||||
|
||||
void TestCase::run(TestResult& result) {
|
||||
result_ = &result;
|
||||
@@ -218,7 +214,7 @@ void TestCase::run(TestResult& result) {
|
||||
// class Runner
|
||||
// //////////////////////////////////////////////////////////////////
|
||||
|
||||
Runner::Runner() {}
|
||||
Runner::Runner() = default;
|
||||
|
||||
Runner& Runner::add(TestCaseFactory factory) {
|
||||
tests_.push_back(factory);
|
||||
@@ -272,8 +268,7 @@ bool Runner::runAllTest(bool printSummary) const {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
for (size_t index = 0; index < failures.size(); ++index) {
|
||||
TestResult& result = failures[index];
|
||||
for (auto& result : failures) {
|
||||
result.printFailure(count > 1);
|
||||
}
|
||||
|
||||
|
@@ -42,7 +42,7 @@ public:
|
||||
/// Must be a POD to allow inline initialisation without stepping
|
||||
/// into the debugger.
|
||||
struct PredicateContext {
|
||||
typedef unsigned int Id;
|
||||
using Id = unsigned int;
|
||||
Id id_;
|
||||
const char* file_;
|
||||
unsigned int line_;
|
||||
@@ -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_;
|
||||
PredicateContext::Id predicateId_{1};
|
||||
|
||||
/// \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 = JSONCPP_NULL);
|
||||
const char* expr = nullptr);
|
||||
|
||||
/// Removes the last PredicateContext added to the predicate stack
|
||||
/// chained list.
|
||||
@@ -84,9 +84,7 @@ public:
|
||||
// Generic operator that will work with anything ostream can deal with.
|
||||
template <typename T> TestResult& operator<<(const T& value) {
|
||||
Json::OStringStream oss;
|
||||
oss.precision(16);
|
||||
oss.setf(std::ios_base::floatfield);
|
||||
oss << value;
|
||||
oss << std::setprecision(16) << std::hexfloat << value;
|
||||
return addToLastFailure(oss.str());
|
||||
}
|
||||
|
||||
@@ -104,13 +102,13 @@ private:
|
||||
static Json::String indentText(const Json::String& text,
|
||||
const Json::String& indent);
|
||||
|
||||
typedef std::deque<Failure> Failures;
|
||||
using Failures = std::deque<Failure>;
|
||||
Failures failures_;
|
||||
Json::String name_;
|
||||
PredicateContext rootPredicateNode_;
|
||||
PredicateContext::Id lastUsedPredicateId_;
|
||||
PredicateContext::Id lastUsedPredicateId_{0};
|
||||
/// Failure which is the target of the messages added using operator <<
|
||||
Failure* messageTarget_;
|
||||
Failure* messageTarget_{nullptr};
|
||||
};
|
||||
|
||||
class TestCase {
|
||||
@@ -124,14 +122,14 @@ public:
|
||||
virtual const char* testName() const = 0;
|
||||
|
||||
protected:
|
||||
TestResult* result_;
|
||||
TestResult* result_{nullptr};
|
||||
|
||||
private:
|
||||
virtual void runTestCase() = 0;
|
||||
};
|
||||
|
||||
/// Function pointer type for TestCase factory
|
||||
typedef TestCase* (*TestCaseFactory)();
|
||||
using TestCaseFactory = TestCase* (*)();
|
||||
|
||||
class Runner {
|
||||
public:
|
||||
@@ -161,8 +159,8 @@ public:
|
||||
static void printUsage(const char* appName);
|
||||
|
||||
private: // prevents copy construction and assignment
|
||||
Runner(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||
Runner& operator=(const Runner& other) JSONCPP_CTOR_DELETE;
|
||||
Runner(const Runner& other) = delete;
|
||||
Runner& operator=(const Runner& other) = delete;
|
||||
|
||||
private:
|
||||
void listTests() const;
|
||||
@@ -170,7 +168,7 @@ private:
|
||||
static void preventDialogOnCrash();
|
||||
|
||||
private:
|
||||
typedef std::deque<TestCaseFactory> Factories;
|
||||
using Factories = std::deque<TestCaseFactory>;
|
||||
Factories tests_;
|
||||
};
|
||||
|
||||
@@ -253,10 +251,8 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
||||
} \
|
||||
\
|
||||
public: /* overridden from TestCase */ \
|
||||
const char* testName() const JSONCPP_OVERRIDE { \
|
||||
return #FixtureType "/" #name; \
|
||||
} \
|
||||
void runTestCase() JSONCPP_OVERRIDE; \
|
||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
||||
void runTestCase() override; \
|
||||
}; \
|
||||
\
|
||||
void Test##FixtureType##name::runTestCase()
|
||||
@@ -280,10 +276,8 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
||||
} \
|
||||
\
|
||||
public: /* overridden from TestCase */ \
|
||||
const char* testName() const JSONCPP_OVERRIDE { \
|
||||
return #FixtureType "/" #name; \
|
||||
} \
|
||||
void runTestCase() JSONCPP_OVERRIDE; \
|
||||
const char* testName() const override { return #FixtureType "/" #name; } \
|
||||
void runTestCase() override; \
|
||||
}; \
|
||||
\
|
||||
static bool test##FixtureType##name##collect = \
|
||||
|
File diff suppressed because it is too large
Load Diff
1
test/data/fail_invalid_quote.json
Normal file
1
test/data/fail_invalid_quote.json
Normal file
@@ -0,0 +1 @@
|
||||
{'//this is bad JSON.'}
|
Reference in New Issue
Block a user