mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 23:20:05 +02:00
Compare commits
169 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b4e88e35be | ||
![]() |
a888632781 | ||
![]() |
dca8a24cf8 | ||
![]() |
3f86349128 | ||
![]() |
2b3815c90d | ||
![]() |
bd25fc5ea0 | ||
![]() |
8214f717e7 | ||
![]() |
07e3d1b076 | ||
![]() |
871f0cc43b | ||
![]() |
54fc4e28ed | ||
![]() |
76ff1db84d | ||
![]() |
89e2973c75 | ||
![]() |
7f36cdb3ea | ||
![]() |
2067f66d66 | ||
![]() |
3aa1192a00 | ||
![]() |
99e8ca69b1 | ||
![]() |
162ead383d | ||
![]() |
4b1bd4405e | ||
![]() |
f459022786 | ||
![]() |
fa0dff18fd | ||
![]() |
48d2e106a7 | ||
![]() |
2072e2b4e3 | ||
![]() |
fdb529bd06 | ||
![]() |
8d1ea7054f | ||
![]() |
d13801e832 | ||
![]() |
d791737ccd | ||
![]() |
a4a083c307 | ||
![]() |
62f7f3efe6 | ||
![]() |
742c645ab3 | ||
![]() |
31754ce2e2 | ||
![]() |
483f1c310e | ||
![]() |
c04c0c2131 | ||
![]() |
c857395951 | ||
![]() |
d39b0dff0c | ||
![]() |
fd1abe4cca | ||
![]() |
badbbc7185 | ||
![]() |
caf5fb0742 | ||
![]() |
57de64bf69 | ||
![]() |
78893d3961 | ||
![]() |
034976a19d | ||
![]() |
e1a3c64fef | ||
![]() |
3c2205cd97 | ||
![]() |
0a9b9d9c6e | ||
![]() |
c3a986600f | ||
![]() |
073ad7e96e | ||
![]() |
65d92a4313 | ||
![]() |
ccea7db6c3 | ||
![]() |
4290915354 | ||
![]() |
cc28be0590 | ||
![]() |
255ebc54af | ||
![]() |
c8166ddf1c | ||
![]() |
73c94501ed | ||
![]() |
d2a9495fda | ||
![]() |
5c003ecacc | ||
![]() |
6668fa51ee | ||
![]() |
79ade90248 | ||
![]() |
01b11d2e4b | ||
![]() |
cd8173c6d3 | ||
![]() |
69098a18b9 | ||
![]() |
3d9bf8ee54 | ||
![]() |
8190e061bc | ||
![]() |
42e892d96e | ||
![]() |
a1f1613bdd | ||
![]() |
2d55c7445f | ||
![]() |
5defb4ed1a | ||
![]() |
c4904b2c0d | ||
![]() |
54a5432c01 | ||
![]() |
b22302e560 | ||
![]() |
29f9853455 | ||
![]() |
fa747b1ae3 | ||
![]() |
94a6220f7c | ||
![]() |
c39fbdac0f | ||
![]() |
65bb1b1c1d | ||
![]() |
375a1119f8 | ||
![]() |
5fabc5e6d2 | ||
![]() |
ed1ab7ac45 | ||
![]() |
bb34617267 | ||
![]() |
993e4e2828 | ||
![]() |
2af4a4c6c8 | ||
![]() |
a3914b792f | ||
![]() |
cee42e0bd7 | ||
![]() |
62f3e03475 | ||
![]() |
b640795571 | ||
![]() |
94cda30dbd | ||
![]() |
1ee39a6752 | ||
![]() |
b1bd848241 | ||
![]() |
09c5ecd84f | ||
![]() |
fda274ddd2 | ||
![]() |
da9e17d257 | ||
![]() |
ac2870298e | ||
![]() |
c9a976238b | ||
![]() |
eab8ebe644 | ||
![]() |
fe9663e7ed | ||
![]() |
5c4219b8ae | ||
![]() |
be4a512887 | ||
![]() |
940982438d | ||
![]() |
8954092f0a | ||
![]() |
ceae0e3867 | ||
![]() |
30170d651c | ||
![]() |
5f4e10462f | ||
![]() |
bb9db78fe2 | ||
![]() |
1664b6bbf8 | ||
![]() |
5d1cb30e40 | ||
![]() |
c60ebf787a | ||
![]() |
72db276986 | ||
![]() |
9059f5cad0 | ||
![]() |
45733df96c | ||
![]() |
5be07bdc5e | ||
![]() |
bf0cfa5b46 | ||
![]() |
cfc1ad72ad | ||
![]() |
c8453d39d1 | ||
![]() |
632044ad95 | ||
![]() |
b3189a0800 | ||
![]() |
9be5895985 | ||
![]() |
6aba23f4a8 | ||
![]() |
c161f4ac69 | ||
![]() |
75b360af4a | ||
![]() |
e36cff19f0 | ||
![]() |
b8cb8889aa | ||
![]() |
d2d4c74a03 | ||
![]() |
8b7ea09b80 | ||
![]() |
a4fb5db543 | ||
![]() |
d517d598a7 | ||
![]() |
e9b0b96be6 | ||
![]() |
3f0d63b5a9 | ||
![]() |
524234e479 | ||
![]() |
9abf11935c | ||
![]() |
8a5e792f20 | ||
![]() |
30eb5ce128 | ||
![]() |
12ceb01485 | ||
![]() |
edc6239f39 | ||
![]() |
5a0152ae1b | ||
![]() |
c648b0378a | ||
![]() |
a3afd74b80 | ||
![]() |
2cb16b35dc | ||
![]() |
83946a28db | ||
![]() |
91f1553f2c | ||
![]() |
5813ab1bc1 | ||
![]() |
a0b8c3ecb4 | ||
![]() |
b349221938 | ||
![]() |
9e23f66f61 | ||
![]() |
411d88fae8 | ||
![]() |
1ff6bb65a0 | ||
![]() |
8b20b7a317 | ||
![]() |
2e54e8ff1c | ||
![]() |
90ca694e46 | ||
![]() |
3beb37ea14 | ||
![]() |
dc180eb25e | ||
![]() |
a6fe8e27d8 | ||
![]() |
edf528edfa | ||
![]() |
6317f9a406 | ||
![]() |
6bc55ec35d | ||
![]() |
f11611c878 | ||
![]() |
8f7f35c5cd | ||
![]() |
7e5485ab5b | ||
![]() |
92d90250f2 | ||
![]() |
d6c4a8fb2d | ||
![]() |
a3c8642886 | ||
![]() |
2983f5a89a | ||
![]() |
a0bd9adfef | ||
![]() |
9e0d70aa66 | ||
![]() |
f200239d5b | ||
![]() |
cfc3e927fc | ||
![]() |
a481201af1 | ||
![]() |
9704cedb20 | ||
![]() |
781eec4da8 | ||
![]() |
1c8f7d8ae5 | ||
![]() |
554d961625 | ||
![]() |
01db7b7430 |
@@ -1,4 +1,4 @@
|
|||||||
BasedOnStyle: LLVM
|
BasedOnStyle: LLVM
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
---
|
---
|
||||||
Checks: 'google-readability-casting,modernize-use-default-member-init,modernize-use-using,readability-redundant-member-init'
|
Checks: 'google-readability-casting,modernize-deprecated-headers,modernize-loop-convert,modernize-use-auto,modernize-use-default-member-init,modernize-use-using,readability-else-after-return,readability-redundant-member-init,readability-redundant-string-cstr'
|
||||||
WarningsAsErrors: ''
|
WarningsAsErrors: ''
|
||||||
HeaderFilterRegex: ''
|
HeaderFilterRegex: ''
|
||||||
AnalyzeTemporaryDtors: false
|
AnalyzeTemporaryDtors: false
|
||||||
FormatStyle: none
|
FormatStyle: none
|
||||||
CheckOptions:
|
CheckOptions:
|
||||||
- key: modernize-use-using.IgnoreMacros
|
- key: modernize-use-using.IgnoreMacros
|
||||||
value: '0'
|
value: '0'
|
||||||
...
|
...
|
||||||
|
20
.github/workflows/clang-format.yml
vendored
Normal file
20
.github/workflows/clang-format.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: clang-format check
|
||||||
|
on: [check_run, pull_request, push]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
formatting-check:
|
||||||
|
name: formatting check
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
path:
|
||||||
|
- 'src'
|
||||||
|
- 'examples'
|
||||||
|
- 'include'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: runs clang-format style check for C/C++/Protobuf programs.
|
||||||
|
uses: jidicula/clang-format-action@v4.13.0
|
||||||
|
with:
|
||||||
|
clang-format-version: '18'
|
||||||
|
check-path: ${{ matrix.path }}
|
18
.github/workflows/cmake.yml
vendored
Normal file
18
.github/workflows/cmake.yml
vendored
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
name: cmake
|
||||||
|
on: [check_run, push, pull_request]
|
||||||
|
jobs:
|
||||||
|
cmake-publish:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: checkout project
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: build project
|
||||||
|
uses: threeal/cmake-action@v2.0.0
|
||||||
|
|
65
.github/workflows/meson.yml
vendored
Normal file
65
.github/workflows/meson.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
name: meson build and test
|
||||||
|
run-name: update pushed to ${{ github.ref }}
|
||||||
|
on: [check_run, push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
meson-publish:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: setup python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
|
||||||
|
- name: meson build
|
||||||
|
uses: BSFishy/meson-build@v1.0.3
|
||||||
|
with:
|
||||||
|
meson-version: 1.5.1
|
||||||
|
ninja-version: 1.11.1.1
|
||||||
|
action: build
|
||||||
|
|
||||||
|
- name: meson test
|
||||||
|
uses: BSFishy/meson-build@v1.0.3
|
||||||
|
with:
|
||||||
|
meson-version: 1.5.1
|
||||||
|
ninja-version: 1.11.1.1
|
||||||
|
action: test
|
||||||
|
|
||||||
|
meson-coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: setup python
|
||||||
|
uses: actions/setup-python@v5
|
||||||
|
|
||||||
|
- name: meson build
|
||||||
|
uses: BSFishy/meson-build@v1.0.3
|
||||||
|
with:
|
||||||
|
meson-version: 1.5.1
|
||||||
|
ninja-version: 1.11.1.1
|
||||||
|
setup-options: -Db_coverage=true
|
||||||
|
action: build
|
||||||
|
|
||||||
|
- name: meson test
|
||||||
|
uses: BSFishy/meson-build@v1.0.3
|
||||||
|
with:
|
||||||
|
meson-version: 1.5.1
|
||||||
|
ninja-version: 1.11.1.1
|
||||||
|
setup-options: -Db_coverage=true
|
||||||
|
action: test
|
||||||
|
|
||||||
|
- name: generate code coverage report
|
||||||
|
uses: threeal/gcovr-action@v1.0.0
|
||||||
|
with:
|
||||||
|
coveralls-send: true
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
6
.gitignore
vendored
6
.gitignore
vendored
@@ -10,6 +10,7 @@
|
|||||||
/libs/
|
/libs/
|
||||||
/doc/doxyfile
|
/doc/doxyfile
|
||||||
/dist/
|
/dist/
|
||||||
|
/.cache/
|
||||||
|
|
||||||
# MSVC project files:
|
# MSVC project files:
|
||||||
*.sln
|
*.sln
|
||||||
@@ -28,9 +29,9 @@
|
|||||||
|
|
||||||
# CMake-generated files:
|
# CMake-generated files:
|
||||||
CMakeFiles/
|
CMakeFiles/
|
||||||
*.cmake
|
|
||||||
/pkg-config/jsoncpp.pc
|
/pkg-config/jsoncpp.pc
|
||||||
jsoncpp_lib_static.dir/
|
jsoncpp_lib_static.dir/
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
# In case someone runs cmake in the root-dir:
|
# In case someone runs cmake in the root-dir:
|
||||||
/CMakeCache.txt
|
/CMakeCache.txt
|
||||||
@@ -51,3 +52,6 @@ jsoncpp_lib_static.dir/
|
|||||||
|
|
||||||
# DS_Store
|
# DS_Store
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# temps
|
||||||
|
/version
|
||||||
|
71
.travis.yml
71
.travis.yml
@@ -1,71 +0,0 @@
|
|||||||
# Build matrix / environment variables are explained on:
|
|
||||||
# http://about.travis-ci.org/docs/user/build-configuration/
|
|
||||||
# This file can be validated on: http://www.yamllint.com/
|
|
||||||
# Or using the Ruby based travel command line tool:
|
|
||||||
# gem install travis --no-rdoc --no-ri
|
|
||||||
# travis lint .travis.yml
|
|
||||||
language: cpp
|
|
||||||
sudo: false
|
|
||||||
addons:
|
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
- clang-format
|
|
||||||
- meson
|
|
||||||
- ninja
|
|
||||||
update: false # do not update homebrew by default
|
|
||||||
apt:
|
|
||||||
sources:
|
|
||||||
- ubuntu-toolchain-r-test
|
|
||||||
- llvm-toolchain-xenial-8
|
|
||||||
packages:
|
|
||||||
- clang-format-8
|
|
||||||
- clang-8
|
|
||||||
- valgrind
|
|
||||||
matrix:
|
|
||||||
allow_failures:
|
|
||||||
- os: osx
|
|
||||||
include:
|
|
||||||
- name: Mac clang meson static release testing
|
|
||||||
os: osx
|
|
||||||
osx_image: xcode11
|
|
||||||
compiler: clang
|
|
||||||
env:
|
|
||||||
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
|
|
||||||
# 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 cmake coverage
|
|
||||||
os: linux
|
|
||||||
dist: xenial
|
|
||||||
compiler: gcc
|
|
||||||
env:
|
|
||||||
CXX=g++
|
|
||||||
CC=gcc
|
|
||||||
DO_Coverage=ON
|
|
||||||
BUILD_TOOL="Unix Makefiles"
|
|
||||||
BUILD_TYPE=Debug
|
|
||||||
LIB_TYPE=shared
|
|
||||||
DESTDIR=/tmp/cmake_json_cpp
|
|
||||||
before_install:
|
|
||||||
- pip install --user cpp-coveralls
|
|
||||||
script: ./.travis_scripts/cmake_builder.sh
|
|
||||||
after_success:
|
|
||||||
- coveralls --include src/lib_json --include include
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
@@ -1,130 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# This script can be used on the command line directly to configure several
|
|
||||||
# different build environments.
|
|
||||||
# This is called by `.travis.yml` via Travis CI.
|
|
||||||
# Travis supplies $TRAVIS_OS_NAME.
|
|
||||||
# http://docs.travis-ci.com/user/multi-os/
|
|
||||||
# Our .travis.yml also defines:
|
|
||||||
|
|
||||||
# - BUILD_TYPE=Release/Debug
|
|
||||||
# - LIB_TYPE=static/shared
|
|
||||||
#
|
|
||||||
# Optional environmental variables
|
|
||||||
# - DESTDIR <- used for setting the install prefix
|
|
||||||
# - BUILD_TOOL=["Unix Makefile"|"Ninja"]
|
|
||||||
# - BUILDNAME <- how to identify this build on the dashboard
|
|
||||||
# - DO_MemCheck <- if set, try to use valgrind
|
|
||||||
# - DO_Coverage <- if set, try to do dashboard coverage testing
|
|
||||||
#
|
|
||||||
|
|
||||||
env_set=1
|
|
||||||
if ${BUILD_TYPE+false}; then
|
|
||||||
echo "BUILD_TYPE not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
if ${LIB_TYPE+false}; then
|
|
||||||
echo "LIB_TYPE not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
if ${CXX+false}; then
|
|
||||||
echo "CXX not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [ ${env_set} -eq 0 ]; then
|
|
||||||
echo "USAGE: CXX=$(which clang++) BUILD_TYPE=[Release|Debug] LIB_TYPE=[static|shared] $0"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=Release LIB_TYPE=shared DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=Debug LIB_TYPE=shared DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=Release LIB_TYPE=static DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=Debug LIB_TYPE=static DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=Release LIB_TYPE=shared DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=Debug LIB_TYPE=shared DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=Release LIB_TYPE=static DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=Debug LIB_TYPE=static DESTDIR=/tmp/cmake_json_cpp $0"
|
|
||||||
|
|
||||||
exit -1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ${DESTDIR+false}; then
|
|
||||||
DESTDIR="/usr/local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# -e: fail on error
|
|
||||||
# -v: show commands
|
|
||||||
# -x: show expanded commands
|
|
||||||
set -vex
|
|
||||||
|
|
||||||
env | sort
|
|
||||||
|
|
||||||
which cmake
|
|
||||||
cmake --version
|
|
||||||
|
|
||||||
echo ${CXX}
|
|
||||||
${CXX} --version
|
|
||||||
_COMPILER_NAME=`basename ${CXX}`
|
|
||||||
if [ "${BUILD_TYPE}" == "shared" ]; then
|
|
||||||
_CMAKE_BUILD_SHARED_LIBS=ON
|
|
||||||
else
|
|
||||||
_CMAKE_BUILD_SHARED_LIBS=OFF
|
|
||||||
fi
|
|
||||||
|
|
||||||
CTEST_TESTING_OPTION="-D ExperimentalTest"
|
|
||||||
# - DO_MemCheck <- if set, try to use valgrind
|
|
||||||
if ! ${DO_MemCheck+false}; then
|
|
||||||
valgrind --version
|
|
||||||
CTEST_TESTING_OPTION="-D ExperimentalMemCheck"
|
|
||||||
else
|
|
||||||
# - DO_Coverage <- if set, try to do dashboard coverage testing
|
|
||||||
if ! ${DO_Coverage+false}; then
|
|
||||||
export CXXFLAGS="-fprofile-arcs -ftest-coverage"
|
|
||||||
export LDFLAGS="-fprofile-arcs -ftest-coverage"
|
|
||||||
CTEST_TESTING_OPTION="-D ExperimentalTest -D ExperimentalCoverage"
|
|
||||||
#gcov --version
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Ninja = Generates build.ninja files.
|
|
||||||
if ${BUILD_TOOL+false}; then
|
|
||||||
BUILD_TOOL="Ninja"
|
|
||||||
export _BUILD_EXE=ninja
|
|
||||||
which ninja
|
|
||||||
ninja --version
|
|
||||||
else
|
|
||||||
# Unix Makefiles = Generates standard UNIX makefiles.
|
|
||||||
export _BUILD_EXE=make
|
|
||||||
fi
|
|
||||||
|
|
||||||
_BUILD_DIR_NAME="build-cmake_${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}_${_BUILD_EXE}"
|
|
||||||
mkdir -p ${_BUILD_DIR_NAME}
|
|
||||||
cd "${_BUILD_DIR_NAME}"
|
|
||||||
if ${BUILDNAME+false}; then
|
|
||||||
_HOSTNAME=`hostname -s`
|
|
||||||
BUILDNAME="${_HOSTNAME}_${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}_${_BUILD_EXE}"
|
|
||||||
fi
|
|
||||||
cmake \
|
|
||||||
-G "${BUILD_TOOL}" \
|
|
||||||
-DBUILDNAME:STRING="${BUILDNAME}" \
|
|
||||||
-DCMAKE_CXX_COMPILER:PATH=${CXX} \
|
|
||||||
-DCMAKE_BUILD_TYPE:STRING=${BUILD_TYPE} \
|
|
||||||
-DBUILD_SHARED_LIBS:BOOL=${_CMAKE_BUILD_SHARED_LIBS} \
|
|
||||||
-DCMAKE_INSTALL_PREFIX:PATH=${DESTDIR} \
|
|
||||||
../
|
|
||||||
|
|
||||||
ctest -C ${BUILD_TYPE} -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild ${CTEST_TESTING_OPTION} -D ExperimentalSubmit
|
|
||||||
# Final step is to verify that installation succeeds
|
|
||||||
cmake --build . --config ${BUILD_TYPE} --target install
|
|
||||||
|
|
||||||
if [ "${DESTDIR}" != "/usr/local" ]; then
|
|
||||||
${_BUILD_EXE} install
|
|
||||||
fi
|
|
||||||
cd -
|
|
||||||
|
|
||||||
if ${CLEANUP+false}; then
|
|
||||||
echo "Skipping cleanup: build directory will persist."
|
|
||||||
else
|
|
||||||
rm -r "${_BUILD_DIR_NAME}"
|
|
||||||
fi
|
|
@@ -1,83 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
# This script can be used on the command line directly to configure several
|
|
||||||
# different build environments.
|
|
||||||
# This is called by `.travis.yml` via Travis CI.
|
|
||||||
# Travis supplies $TRAVIS_OS_NAME.
|
|
||||||
# http://docs.travis-ci.com/user/multi-os/
|
|
||||||
# Our .travis.yml also defines:
|
|
||||||
|
|
||||||
# - BUILD_TYPE=release/debug
|
|
||||||
# - LIB_TYPE=static/shared
|
|
||||||
|
|
||||||
env_set=1
|
|
||||||
if ${BUILD_TYPE+false}; then
|
|
||||||
echo "BUILD_TYPE not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
if ${LIB_TYPE+false}; then
|
|
||||||
echo "LIB_TYPE not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
if ${CXX+false}; then
|
|
||||||
echo "CXX not set in environment."
|
|
||||||
env_set=0
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
if [ ${env_set} -eq 0 ]; then
|
|
||||||
echo "USAGE: CXX=$(which clang++) BUILD_TYPE=[release|debug] LIB_TYPE=[static|shared] $0"
|
|
||||||
echo ""
|
|
||||||
echo "Examples:"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=release LIB_TYPE=shared DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=debug LIB_TYPE=shared DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=release LIB_TYPE=static DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which clang++) BUILD_TYPE=debug LIB_TYPE=static DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=release LIB_TYPE=shared DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=debug LIB_TYPE=shared DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=release LIB_TYPE=static DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
echo " CXX=$(which g++) BUILD_TYPE=debug LIB_TYPE=static DESTDIR=/tmp/meson_json_cpp $0"
|
|
||||||
|
|
||||||
exit -1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ${DESTDIR+false}; then
|
|
||||||
DESTDIR="/usr/local"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# -e: fail on error
|
|
||||||
# -v: show commands
|
|
||||||
# -x: show expanded commands
|
|
||||||
set -vex
|
|
||||||
|
|
||||||
|
|
||||||
env | sort
|
|
||||||
|
|
||||||
which python3
|
|
||||||
which meson
|
|
||||||
which ninja
|
|
||||||
echo ${CXX}
|
|
||||||
${CXX} --version
|
|
||||||
python3 --version
|
|
||||||
meson --version
|
|
||||||
ninja --version
|
|
||||||
_COMPILER_NAME=`basename ${CXX}`
|
|
||||||
_BUILD_DIR_NAME="build-${BUILD_TYPE}_${LIB_TYPE}_${_COMPILER_NAME}"
|
|
||||||
|
|
||||||
./.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 test --no-rebuild --print-errorlogs
|
|
||||||
|
|
||||||
if [ "${DESTDIR}" != "/usr/local" ]; then
|
|
||||||
ninja install
|
|
||||||
fi
|
|
||||||
cd -
|
|
||||||
|
|
||||||
if ${CLEANUP+false}; then
|
|
||||||
echo "Skipping cleanup: build directory will persist."
|
|
||||||
else
|
|
||||||
rm -r "${_BUILD_DIR_NAME}"
|
|
||||||
fi
|
|
@@ -1,356 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""A wrapper script around clang-format, suitable for linting multiple files
|
|
||||||
and to use for continuous integration.
|
|
||||||
This is an alternative API for the clang-format command line.
|
|
||||||
It runs over multiple files and directories in parallel.
|
|
||||||
A diff output is produced and a sensible exit code is returned.
|
|
||||||
|
|
||||||
NOTE: pulled from https://github.com/Sarcasm/run-clang-format, which is
|
|
||||||
licensed under the MIT license.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import codecs
|
|
||||||
import difflib
|
|
||||||
import fnmatch
|
|
||||||
import io
|
|
||||||
import multiprocessing
|
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from functools import partial
|
|
||||||
|
|
||||||
try:
|
|
||||||
from subprocess import DEVNULL # py3k
|
|
||||||
except ImportError:
|
|
||||||
DEVNULL = open(os.devnull, "wb")
|
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_EXTENSIONS = 'c,h,C,H,cpp,hpp,cc,hh,c++,h++,cxx,hxx'
|
|
||||||
|
|
||||||
|
|
||||||
class ExitStatus:
|
|
||||||
SUCCESS = 0
|
|
||||||
DIFF = 1
|
|
||||||
TROUBLE = 2
|
|
||||||
|
|
||||||
|
|
||||||
def list_files(files, recursive=False, extensions=None, exclude=None):
|
|
||||||
if extensions is None:
|
|
||||||
extensions = []
|
|
||||||
if exclude is None:
|
|
||||||
exclude = []
|
|
||||||
|
|
||||||
out = []
|
|
||||||
for file in files:
|
|
||||||
if recursive and os.path.isdir(file):
|
|
||||||
for dirpath, dnames, fnames in os.walk(file):
|
|
||||||
fpaths = [os.path.join(dirpath, fname) for fname in fnames]
|
|
||||||
for pattern in exclude:
|
|
||||||
# os.walk() supports trimming down the dnames list
|
|
||||||
# by modifying it in-place,
|
|
||||||
# to avoid unnecessary directory listings.
|
|
||||||
dnames[:] = [
|
|
||||||
x for x in dnames
|
|
||||||
if
|
|
||||||
not fnmatch.fnmatch(os.path.join(dirpath, x), pattern)
|
|
||||||
]
|
|
||||||
fpaths = [
|
|
||||||
x for x in fpaths if not fnmatch.fnmatch(x, pattern)
|
|
||||||
]
|
|
||||||
for f in fpaths:
|
|
||||||
ext = os.path.splitext(f)[1][1:]
|
|
||||||
if ext in extensions:
|
|
||||||
out.append(f)
|
|
||||||
else:
|
|
||||||
out.append(file)
|
|
||||||
return out
|
|
||||||
|
|
||||||
|
|
||||||
def make_diff(file, original, reformatted):
|
|
||||||
return list(
|
|
||||||
difflib.unified_diff(
|
|
||||||
original,
|
|
||||||
reformatted,
|
|
||||||
fromfile='{}\t(original)'.format(file),
|
|
||||||
tofile='{}\t(reformatted)'.format(file),
|
|
||||||
n=3))
|
|
||||||
|
|
||||||
|
|
||||||
class DiffError(Exception):
|
|
||||||
def __init__(self, message, errs=None):
|
|
||||||
super(DiffError, self).__init__(message)
|
|
||||||
self.errs = errs or []
|
|
||||||
|
|
||||||
|
|
||||||
class UnexpectedError(Exception):
|
|
||||||
def __init__(self, message, exc=None):
|
|
||||||
super(UnexpectedError, self).__init__(message)
|
|
||||||
self.formatted_traceback = traceback.format_exc()
|
|
||||||
self.exc = exc
|
|
||||||
|
|
||||||
|
|
||||||
def run_clang_format_diff_wrapper(args, file):
|
|
||||||
try:
|
|
||||||
ret = run_clang_format_diff(args, file)
|
|
||||||
return ret
|
|
||||||
except DiffError:
|
|
||||||
raise
|
|
||||||
except Exception as e:
|
|
||||||
raise UnexpectedError('{}: {}: {}'.format(file, e.__class__.__name__,
|
|
||||||
e), e)
|
|
||||||
|
|
||||||
|
|
||||||
def run_clang_format_diff(args, file):
|
|
||||||
try:
|
|
||||||
with io.open(file, 'r', encoding='utf-8') as f:
|
|
||||||
original = f.readlines()
|
|
||||||
except IOError as exc:
|
|
||||||
raise DiffError(str(exc))
|
|
||||||
invocation = [args.clang_format_executable, file]
|
|
||||||
|
|
||||||
# Use of utf-8 to decode the process output.
|
|
||||||
#
|
|
||||||
# Hopefully, this is the correct thing to do.
|
|
||||||
#
|
|
||||||
# It's done due to the following assumptions (which may be incorrect):
|
|
||||||
# - clang-format will returns the bytes read from the files as-is,
|
|
||||||
# without conversion, and it is already assumed that the files use utf-8.
|
|
||||||
# - if the diagnostics were internationalized, they would use utf-8:
|
|
||||||
# > Adding Translations to Clang
|
|
||||||
# >
|
|
||||||
# > Not possible yet!
|
|
||||||
# > Diagnostic strings should be written in UTF-8,
|
|
||||||
# > the client can translate to the relevant code page if needed.
|
|
||||||
# > Each translation completely replaces the format string
|
|
||||||
# > for the diagnostic.
|
|
||||||
# > -- http://clang.llvm.org/docs/InternalsManual.html#internals-diag-translation
|
|
||||||
#
|
|
||||||
# It's not pretty, due to Python 2 & 3 compatibility.
|
|
||||||
encoding_py3 = {}
|
|
||||||
if sys.version_info[0] >= 3:
|
|
||||||
encoding_py3['encoding'] = 'utf-8'
|
|
||||||
|
|
||||||
try:
|
|
||||||
proc = subprocess.Popen(
|
|
||||||
invocation,
|
|
||||||
stdout=subprocess.PIPE,
|
|
||||||
stderr=subprocess.PIPE,
|
|
||||||
universal_newlines=True,
|
|
||||||
**encoding_py3)
|
|
||||||
except OSError as exc:
|
|
||||||
raise DiffError(
|
|
||||||
"Command '{}' failed to start: {}".format(
|
|
||||||
subprocess.list2cmdline(invocation), exc
|
|
||||||
)
|
|
||||||
)
|
|
||||||
proc_stdout = proc.stdout
|
|
||||||
proc_stderr = proc.stderr
|
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
# make the pipes compatible with Python 3,
|
|
||||||
# reading lines should output unicode
|
|
||||||
encoding = 'utf-8'
|
|
||||||
proc_stdout = codecs.getreader(encoding)(proc_stdout)
|
|
||||||
proc_stderr = codecs.getreader(encoding)(proc_stderr)
|
|
||||||
# hopefully the stderr pipe won't get full and block the process
|
|
||||||
outs = list(proc_stdout.readlines())
|
|
||||||
errs = list(proc_stderr.readlines())
|
|
||||||
proc.wait()
|
|
||||||
if proc.returncode:
|
|
||||||
raise DiffError(
|
|
||||||
"Command '{}' returned non-zero exit status {}".format(
|
|
||||||
subprocess.list2cmdline(invocation), proc.returncode
|
|
||||||
),
|
|
||||||
errs,
|
|
||||||
)
|
|
||||||
return make_diff(file, original, outs), errs
|
|
||||||
|
|
||||||
|
|
||||||
def bold_red(s):
|
|
||||||
return '\x1b[1m\x1b[31m' + s + '\x1b[0m'
|
|
||||||
|
|
||||||
|
|
||||||
def colorize(diff_lines):
|
|
||||||
def bold(s):
|
|
||||||
return '\x1b[1m' + s + '\x1b[0m'
|
|
||||||
|
|
||||||
def cyan(s):
|
|
||||||
return '\x1b[36m' + s + '\x1b[0m'
|
|
||||||
|
|
||||||
def green(s):
|
|
||||||
return '\x1b[32m' + s + '\x1b[0m'
|
|
||||||
|
|
||||||
def red(s):
|
|
||||||
return '\x1b[31m' + s + '\x1b[0m'
|
|
||||||
|
|
||||||
for line in diff_lines:
|
|
||||||
if line[:4] in ['--- ', '+++ ']:
|
|
||||||
yield bold(line)
|
|
||||||
elif line.startswith('@@ '):
|
|
||||||
yield cyan(line)
|
|
||||||
elif line.startswith('+'):
|
|
||||||
yield green(line)
|
|
||||||
elif line.startswith('-'):
|
|
||||||
yield red(line)
|
|
||||||
else:
|
|
||||||
yield line
|
|
||||||
|
|
||||||
|
|
||||||
def print_diff(diff_lines, use_color):
|
|
||||||
if use_color:
|
|
||||||
diff_lines = colorize(diff_lines)
|
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
sys.stdout.writelines((l.encode('utf-8') for l in diff_lines))
|
|
||||||
else:
|
|
||||||
sys.stdout.writelines(diff_lines)
|
|
||||||
|
|
||||||
|
|
||||||
def print_trouble(prog, message, use_colors):
|
|
||||||
error_text = 'error:'
|
|
||||||
if use_colors:
|
|
||||||
error_text = bold_red(error_text)
|
|
||||||
print("{}: {} {}".format(prog, error_text, message), file=sys.stderr)
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
parser = argparse.ArgumentParser(description=__doc__)
|
|
||||||
parser.add_argument(
|
|
||||||
'--clang-format-executable',
|
|
||||||
metavar='EXECUTABLE',
|
|
||||||
help='path to the clang-format executable',
|
|
||||||
default='clang-format')
|
|
||||||
parser.add_argument(
|
|
||||||
'--extensions',
|
|
||||||
help='comma separated list of file extensions (default: {})'.format(
|
|
||||||
DEFAULT_EXTENSIONS),
|
|
||||||
default=DEFAULT_EXTENSIONS)
|
|
||||||
parser.add_argument(
|
|
||||||
'-r',
|
|
||||||
'--recursive',
|
|
||||||
action='store_true',
|
|
||||||
help='run recursively over directories')
|
|
||||||
parser.add_argument('files', metavar='file', nargs='+')
|
|
||||||
parser.add_argument(
|
|
||||||
'-q',
|
|
||||||
'--quiet',
|
|
||||||
action='store_true')
|
|
||||||
parser.add_argument(
|
|
||||||
'-j',
|
|
||||||
metavar='N',
|
|
||||||
type=int,
|
|
||||||
default=0,
|
|
||||||
help='run N clang-format jobs in parallel'
|
|
||||||
' (default number of cpus + 1)')
|
|
||||||
parser.add_argument(
|
|
||||||
'--color',
|
|
||||||
default='auto',
|
|
||||||
choices=['auto', 'always', 'never'],
|
|
||||||
help='show colored diff (default: auto)')
|
|
||||||
parser.add_argument(
|
|
||||||
'-e',
|
|
||||||
'--exclude',
|
|
||||||
metavar='PATTERN',
|
|
||||||
action='append',
|
|
||||||
default=[],
|
|
||||||
help='exclude paths matching the given glob-like pattern(s)'
|
|
||||||
' from recursive search')
|
|
||||||
|
|
||||||
args = parser.parse_args()
|
|
||||||
|
|
||||||
# use default signal handling, like diff return SIGINT value on ^C
|
|
||||||
# https://bugs.python.org/issue14229#msg156446
|
|
||||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
|
||||||
try:
|
|
||||||
signal.SIGPIPE
|
|
||||||
except AttributeError:
|
|
||||||
# compatibility, SIGPIPE does not exist on Windows
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
|
|
||||||
|
|
||||||
colored_stdout = False
|
|
||||||
colored_stderr = False
|
|
||||||
if args.color == 'always':
|
|
||||||
colored_stdout = True
|
|
||||||
colored_stderr = True
|
|
||||||
elif args.color == 'auto':
|
|
||||||
colored_stdout = sys.stdout.isatty()
|
|
||||||
colored_stderr = sys.stderr.isatty()
|
|
||||||
|
|
||||||
version_invocation = [args.clang_format_executable, str("--version")]
|
|
||||||
try:
|
|
||||||
subprocess.check_call(version_invocation, stdout=DEVNULL)
|
|
||||||
except subprocess.CalledProcessError as e:
|
|
||||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
|
||||||
return ExitStatus.TROUBLE
|
|
||||||
except OSError as e:
|
|
||||||
print_trouble(
|
|
||||||
parser.prog,
|
|
||||||
"Command '{}' failed to start: {}".format(
|
|
||||||
subprocess.list2cmdline(version_invocation), e
|
|
||||||
),
|
|
||||||
use_colors=colored_stderr,
|
|
||||||
)
|
|
||||||
return ExitStatus.TROUBLE
|
|
||||||
|
|
||||||
retcode = ExitStatus.SUCCESS
|
|
||||||
files = list_files(
|
|
||||||
args.files,
|
|
||||||
recursive=args.recursive,
|
|
||||||
exclude=args.exclude,
|
|
||||||
extensions=args.extensions.split(','))
|
|
||||||
|
|
||||||
if not files:
|
|
||||||
return
|
|
||||||
|
|
||||||
njobs = args.j
|
|
||||||
if njobs == 0:
|
|
||||||
njobs = multiprocessing.cpu_count() + 1
|
|
||||||
njobs = min(len(files), njobs)
|
|
||||||
|
|
||||||
if njobs == 1:
|
|
||||||
# execute directly instead of in a pool,
|
|
||||||
# less overhead, simpler stacktraces
|
|
||||||
it = (run_clang_format_diff_wrapper(args, file) for file in files)
|
|
||||||
pool = None
|
|
||||||
else:
|
|
||||||
pool = multiprocessing.Pool(njobs)
|
|
||||||
it = pool.imap_unordered(
|
|
||||||
partial(run_clang_format_diff_wrapper, args), files)
|
|
||||||
while True:
|
|
||||||
try:
|
|
||||||
outs, errs = next(it)
|
|
||||||
except StopIteration:
|
|
||||||
break
|
|
||||||
except DiffError as e:
|
|
||||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
|
||||||
retcode = ExitStatus.TROUBLE
|
|
||||||
sys.stderr.writelines(e.errs)
|
|
||||||
except UnexpectedError as e:
|
|
||||||
print_trouble(parser.prog, str(e), use_colors=colored_stderr)
|
|
||||||
sys.stderr.write(e.formatted_traceback)
|
|
||||||
retcode = ExitStatus.TROUBLE
|
|
||||||
# stop at the first unexpected error,
|
|
||||||
# something could be very wrong,
|
|
||||||
# don't process all files unnecessarily
|
|
||||||
if pool:
|
|
||||||
pool.terminate()
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
sys.stderr.writelines(errs)
|
|
||||||
if outs == []:
|
|
||||||
continue
|
|
||||||
if not args.quiet:
|
|
||||||
print_diff(outs, use_color=colored_stdout)
|
|
||||||
if retcode == ExitStatus.SUCCESS:
|
|
||||||
retcode = ExitStatus.DIFF
|
|
||||||
return retcode
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
@@ -1,4 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
|
||||||
python $DIR/run-clang-format.py -r $DIR/../src/**/ $DIR/../include/**/
|
|
@@ -1,8 +0,0 @@
|
|||||||
set -vex
|
|
||||||
|
|
||||||
# Preinstalled versions of python are dependent on which Ubuntu distribution
|
|
||||||
# you are running. The below version needs to be updated whenever we roll
|
|
||||||
# the Ubuntu version used in Travis.
|
|
||||||
# https://docs.travis-ci.com/user/languages/python/
|
|
||||||
|
|
||||||
pyenv global 3.7.1
|
|
@@ -1 +0,0 @@
|
|||||||
# NOTHING TO DO HERE
|
|
@@ -1,10 +0,0 @@
|
|||||||
set -vex
|
|
||||||
|
|
||||||
wget https://github.com/ninja-build/ninja/releases/download/v1.9.0/ninja-linux.zip
|
|
||||||
unzip -q ninja-linux.zip -d build
|
|
||||||
|
|
||||||
pip3 install meson
|
|
||||||
echo ${PATH}
|
|
||||||
ls /usr/local
|
|
||||||
ls /usr/local/bin
|
|
||||||
export PATH="${PWD}"/build:/usr/local/bin:/usr/bin:${PATH}
|
|
@@ -1 +0,0 @@
|
|||||||
# NOTHING TO DO HERE
|
|
4
AUTHORS
4
AUTHORS
@@ -16,11 +16,12 @@ Baruch Siach <baruch@tkos.co.il>
|
|||||||
Ben Boeckel <mathstuf@gmail.com>
|
Ben Boeckel <mathstuf@gmail.com>
|
||||||
Benjamin Knecht <bknecht@logitech.com>
|
Benjamin Knecht <bknecht@logitech.com>
|
||||||
Bernd Kuhls <bernd.kuhls@t-online.de>
|
Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||||
Billy Donahue <billydonahue@google.com>
|
Billy Donahue <billy.donahue@gmail.com>
|
||||||
Braden McDorman <bmcdorman@gmail.com>
|
Braden McDorman <bmcdorman@gmail.com>
|
||||||
Brandon Myers <bmyers1788@gmail.com>
|
Brandon Myers <bmyers1788@gmail.com>
|
||||||
Brendan Drew <brendan.drew@daqri.com>
|
Brendan Drew <brendan.drew@daqri.com>
|
||||||
chason <cxchao802@gmail.com>
|
chason <cxchao802@gmail.com>
|
||||||
|
chenguoping <chenguopingdota@163.com>
|
||||||
Chris Gilling <cgilling@iparadigms.com>
|
Chris Gilling <cgilling@iparadigms.com>
|
||||||
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||||
Christopher Dunn <cdunn2001@gmail.com>
|
Christopher Dunn <cdunn2001@gmail.com>
|
||||||
@@ -97,6 +98,7 @@ selaselah <selah@outlook.com>
|
|||||||
Sergiy80 <sil2004@gmail.com>
|
Sergiy80 <sil2004@gmail.com>
|
||||||
sergzub <sergzub@gmail.com>
|
sergzub <sergzub@gmail.com>
|
||||||
Stefan Schweter <stefan@schweter.it>
|
Stefan Schweter <stefan@schweter.it>
|
||||||
|
Stefano Fiorentino <stefano.fiore84@gmail.com>
|
||||||
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
||||||
Steven Hahn <hahnse@ornl.gov>
|
Steven Hahn <hahnse@ornl.gov>
|
||||||
Stuart Eichert <stuart@fivemicro.com>
|
Stuart Eichert <stuart@fivemicro.com>
|
||||||
|
37
BUILD.bazel
Normal file
37
BUILD.bazel
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
licenses(["unencumbered"]) # Public Domain or MIT
|
||||||
|
|
||||||
|
exports_files(["LICENSE"])
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "jsoncpp",
|
||||||
|
srcs = [
|
||||||
|
"src/lib_json/json_reader.cpp",
|
||||||
|
"src/lib_json/json_tool.h",
|
||||||
|
"src/lib_json/json_value.cpp",
|
||||||
|
"src/lib_json/json_writer.cpp",
|
||||||
|
],
|
||||||
|
hdrs = [
|
||||||
|
"include/json/allocator.h",
|
||||||
|
"include/json/assertions.h",
|
||||||
|
"include/json/config.h",
|
||||||
|
"include/json/json_features.h",
|
||||||
|
"include/json/forwards.h",
|
||||||
|
"include/json/json.h",
|
||||||
|
"include/json/reader.h",
|
||||||
|
"include/json/value.h",
|
||||||
|
"include/json/version.h",
|
||||||
|
"include/json/writer.h",
|
||||||
|
],
|
||||||
|
copts = [
|
||||||
|
"-DJSON_USE_EXCEPTION=0",
|
||||||
|
"-DJSON_HAS_INT64",
|
||||||
|
],
|
||||||
|
includes = ["include"],
|
||||||
|
visibility = ["//visibility:public"],
|
||||||
|
deps = [":private"],
|
||||||
|
)
|
||||||
|
|
||||||
|
cc_library(
|
||||||
|
name = "private",
|
||||||
|
textual_hdrs = ["src/lib_json/json_valueiterator.inl"],
|
||||||
|
)
|
202
CMakeLists.txt
202
CMakeLists.txt
@@ -6,7 +6,7 @@
|
|||||||
# policies that provide successful builds. By setting JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
# policies that provide successful builds. By setting JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
||||||
# to a value greater than the oldest policies, all policies between
|
# to a value greater than the oldest policies, all policies between
|
||||||
# JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION (used for this build)
|
# JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION (used for this build)
|
||||||
# are set to their NEW behaivor, thereby suppressing policy warnings related to policies
|
# are set to their NEW behavior, thereby suppressing policy warnings related to policies
|
||||||
# between the JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION.
|
# between the JSONCPP_OLDEST_VALIDATED_POLICIES_VERSION and CMAKE_VERSION.
|
||||||
#
|
#
|
||||||
# CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will
|
# CMake versions greater than the JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION policies will
|
||||||
@@ -22,6 +22,9 @@ else()
|
|||||||
set(JSONCPP_CMAKE_POLICY_VERSION "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")
|
set(JSONCPP_CMAKE_POLICY_VERSION "${JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION}")
|
||||||
endif()
|
endif()
|
||||||
cmake_policy(VERSION ${JSONCPP_CMAKE_POLICY_VERSION})
|
cmake_policy(VERSION ${JSONCPP_CMAKE_POLICY_VERSION})
|
||||||
|
if(POLICY CMP0091)
|
||||||
|
cmake_policy(SET CMP0091 NEW)
|
||||||
|
endif()
|
||||||
#
|
#
|
||||||
# Now enumerate specific policies newer than JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
# Now enumerate specific policies newer than JSONCPP_NEWEST_VALIDATED_POLICIES_VERSION
|
||||||
# that may need to be individually set to NEW/OLD
|
# that may need to be individually set to NEW/OLD
|
||||||
@@ -37,44 +40,36 @@ foreach(pold "") # Currently Empty
|
|||||||
endif()
|
endif()
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
# ==== Define language standard configurations requiring at least c++11 standard
|
# Build the library with C++11 standard support, independent from other including
|
||||||
if(CMAKE_CXX_STANDARD EQUAL "98" )
|
# software which may use a different CXX_STANDARD or CMAKE_CXX_STANDARD.
|
||||||
message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported.")
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
endif()
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
|
||||||
#####
|
# Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
|
||||||
## Set the default target properties
|
if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
|
||||||
set(CMAKE_CXX_STANDARD 11) # Supported values are ``11``, ``14``, and ``17``.
|
|
||||||
endif()
|
|
||||||
if(NOT CMAKE_CXX_STANDARD_REQUIRED)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
endif()
|
|
||||||
if(NOT CMAKE_CXX_EXTENSIONS)
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ====
|
|
||||||
|
|
||||||
# Ensures that CMAKE_BUILD_TYPE has a default value
|
|
||||||
if(NOT DEFINED CMAKE_BUILD_TYPE)
|
|
||||||
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
set(CMAKE_BUILD_TYPE Release CACHE STRING
|
||||||
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
|
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
project(JSONCPP
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||||
|
|
||||||
|
project(jsoncpp
|
||||||
# Note: version must be updated in three places when doing a release. This
|
# Note: version must be updated in three places when doing a release. This
|
||||||
# annoying process ensures that amalgamate, CMake, and meson all report the
|
# annoying process ensures that amalgamate, CMake, and meson all report the
|
||||||
# correct version.
|
# correct version.
|
||||||
# 1. /meson.build
|
# 1. ./meson.build
|
||||||
# 2. /include/json/version.h
|
# 2. ./include/json/version.h
|
||||||
# 3. /CMakeLists.txt
|
# 3. ./CMakeLists.txt
|
||||||
# IMPORTANT: also update the SOVERSION!!
|
# IMPORTANT: also update the PROJECT_SOVERSION!!
|
||||||
VERSION 1.9.2 # <major>[.<minor>[.<patch>[.<tweak>]]]
|
VERSION 1.9.7 # <major>[.<minor>[.<patch>[.<tweak>]]]
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
|
||||||
message(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
|
message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
|
||||||
set( JSONCPP_SOVERSION 22 )
|
set(PROJECT_SOVERSION 27)
|
||||||
|
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInSourceBuilds.cmake)
|
||||||
|
include(${CMAKE_CURRENT_SOURCE_DIR}/include/PreventInBuildInstalls.cmake)
|
||||||
|
|
||||||
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
|
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
|
||||||
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
|
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
|
||||||
@@ -82,120 +77,100 @@ option(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occ
|
|||||||
option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON)
|
option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON)
|
||||||
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
|
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
|
||||||
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
|
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
|
||||||
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF)
|
option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
|
||||||
|
option(JSONCPP_STATIC_WINDOWS_RUNTIME "Use static (MT/MTd) Windows runtime" OFF)
|
||||||
# Enable runtime search path support for dynamic libraries on OSX
|
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
|
||||||
if(APPLE)
|
option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
|
||||||
set(CMAKE_MACOSX_RPATH 1)
|
option(BUILD_OBJECT_LIBS "Build jsoncpp_lib as a object library." ON)
|
||||||
endif()
|
|
||||||
|
|
||||||
# Adhere to GNU filesystem layout conventions
|
# Adhere to GNU filesystem layout conventions
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
set(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build")
|
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||||
|
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Archive output dir.")
|
||||||
|
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Library output dir.")
|
||||||
|
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "PDB (MSVC debug symbol)output dir.")
|
||||||
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL" )
|
include(CheckFunctionExists)
|
||||||
|
check_function_exists(memset_s HAVE_MEMSET_S)
|
||||||
|
if(HAVE_MEMSET_S)
|
||||||
|
add_definitions("-DHAVE_MEMSET_S=1")
|
||||||
|
endif()
|
||||||
|
|
||||||
configure_file( "${PROJECT_SOURCE_DIR}/version.in"
|
if(JSONCPP_USE_SECURE_MEMORY)
|
||||||
"${PROJECT_BINARY_DIR}/version"
|
add_definitions("-DJSONCPP_USE_SECURE_MEMORY=1")
|
||||||
NEWLINE_STYLE UNIX )
|
endif()
|
||||||
|
|
||||||
macro(UseCompilationWarningAsError)
|
configure_file("${PROJECT_SOURCE_DIR}/version.in"
|
||||||
|
"${PROJECT_BINARY_DIR}/version"
|
||||||
|
NEWLINE_STYLE UNIX)
|
||||||
|
|
||||||
|
macro(use_compilation_warning_as_error)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Only enabled in debug because some old versions of VS STL generate
|
# Only enabled in debug because some old versions of VS STL generate
|
||||||
# warnings when compiled in release configuration.
|
# warnings when compiled in release configuration.
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options($<$<CONFIG:Debug>:/WX>)
|
||||||
add_compile_options($<$<CONFIG:Debug>:/WX>)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
|
|
||||||
endif()
|
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Werror)
|
||||||
add_compile_options(-Werror)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
|
||||||
endif()
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO)
|
if(JSONCPP_WITH_STRICT_ISO)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
|
||||||
add_compile_options(-pedantic-errors)
|
add_compile_options(-pedantic-errors)
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
# Include our configuration header
|
# Include our configuration header
|
||||||
include_directories( ${jsoncpp_SOURCE_DIR}/include )
|
include_directories(${jsoncpp_SOURCE_DIR}/include)
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Only enabled in debug because some old versions of VS STL generate
|
# Only enabled in debug because some old versions of VS STL generate
|
||||||
# unreachable code warning when compiled in release configuration.
|
# unreachable code warning when compiled in release configuration.
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options($<$<CONFIG:Debug>:/W4>)
|
||||||
add_compile_options($<$<CONFIG:Debug>:/W4>)
|
if (JSONCPP_STATIC_WINDOWS_RUNTIME)
|
||||||
else()
|
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# using regular Clang or AppleClang
|
# using regular Clang or AppleClang
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall -Wconversion -Wshadow)
|
||||||
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
|
|
||||||
else()
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare")
|
add_compile_options(-Werror=conversion -Werror=sign-compare)
|
||||||
endif()
|
endif()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
# using GCC
|
# using GCC
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
||||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
|
|
||||||
endif()
|
|
||||||
# not yet ready for -Wsign-conversion
|
# not yet ready for -Wsign-conversion
|
||||||
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO)
|
if(JSONCPP_WITH_STRICT_ISO)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wpedantic)
|
||||||
add_compile_options(-pedantic)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
|
||||||
add_compile_options(-Werror=conversion)
|
add_compile_options(-Werror=conversion)
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||||
# using Intel compiler
|
# using Intel compiler
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
|
||||||
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
|
|
||||||
else()
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
add_compile_options(-Werror=conversion)
|
||||||
add_compile_options(-pedantic)
|
elseif(JSONCPP_WITH_STRICT_ISO)
|
||||||
else()
|
add_compile_options(-Wpedantic)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_program(CCACHE_FOUND ccache)
|
|
||||||
if(CCACHE_FOUND)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
|
|
||||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
|
|
||||||
endif(CCACHE_FOUND)
|
|
||||||
|
|
||||||
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
if(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
UseCompilationWarningAsError()
|
use_compilation_warning_as_error()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||||
|
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(
|
configure_file(
|
||||||
"pkg-config/jsoncpp.pc.in"
|
"pkg-config/jsoncpp.pc.in"
|
||||||
"pkg-config/jsoncpp.pc"
|
"pkg-config/jsoncpp.pc"
|
||||||
@@ -205,27 +180,34 @@ if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
include (CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
install(EXPORT jsoncpp
|
install(EXPORT jsoncpp
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
||||||
FILE jsoncppConfig.cmake)
|
FILE jsoncpp-targets.cmake)
|
||||||
write_basic_package_version_file ("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
configure_package_config_file(jsoncppConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake
|
||||||
VERSION ${PROJECT_VERSION}
|
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||||
COMPATIBILITY SameMajorVersion)
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
|
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
|
||||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
VERSION ${PROJECT_VERSION}
|
||||||
|
COMPATIBILITY SameMajorVersion)
|
||||||
|
install(FILES
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfig.cmake
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/jsoncpp-namespaced-targets.cmake
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(JSONCPP_WITH_TESTS)
|
if(JSONCPP_WITH_TESTS)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
include(CTest)
|
include(CTest)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build the different applications
|
# Build the different applications
|
||||||
add_subdirectory( src )
|
add_subdirectory(src)
|
||||||
|
|
||||||
#install the includes
|
#install the includes
|
||||||
add_subdirectory( include )
|
add_subdirectory(include)
|
||||||
|
|
||||||
#install the example
|
#install the example
|
||||||
add_subdirectory( example )
|
if(JSONCPP_WITH_EXAMPLE)
|
||||||
|
add_subdirectory(example)
|
||||||
|
endif()
|
||||||
|
@@ -19,7 +19,7 @@ If you wish to install to a directory other than /usr/local, set an environment
|
|||||||
DESTDIR=/path/to/install/dir
|
DESTDIR=/path/to/install/dir
|
||||||
|
|
||||||
Then,
|
Then,
|
||||||
|
```sh
|
||||||
cd jsoncpp/
|
cd jsoncpp/
|
||||||
BUILD_TYPE=debug
|
BUILD_TYPE=debug
|
||||||
#BUILD_TYPE=release
|
#BUILD_TYPE=release
|
||||||
@@ -27,9 +27,15 @@ Then,
|
|||||||
#LIB_TYPE=static
|
#LIB_TYPE=static
|
||||||
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
||||||
ninja -v -C build-${LIB_TYPE}
|
ninja -v -C build-${LIB_TYPE}
|
||||||
cd build-${LIB_TYPE}
|
|
||||||
meson test --no-rebuild --print-errorlogs
|
ninja -C build-static/ test
|
||||||
|
|
||||||
|
# Or
|
||||||
|
#cd build-${LIB_TYPE}
|
||||||
|
#meson test --no-rebuild --print-errorlogs
|
||||||
|
|
||||||
sudo ninja install
|
sudo ninja install
|
||||||
|
```
|
||||||
|
|
||||||
## Building and testing with other build systems
|
## Building and testing with other build systems
|
||||||
See https://github.com/open-source-parsers/jsoncpp/wiki/Building
|
See https://github.com/open-source-parsers/jsoncpp/wiki/Building
|
||||||
@@ -71,7 +77,7 @@ See `doxybuild.py --help` for options.
|
|||||||
To add a test, you need to create two files in test/data:
|
To add a test, you need to create two files in test/data:
|
||||||
|
|
||||||
* a `TESTNAME.json` file, that contains the input document in JSON format.
|
* a `TESTNAME.json` file, that contains the input document in JSON format.
|
||||||
* a `TESTNAME.expected` file, that contains a flatened representation of the
|
* a `TESTNAME.expected` file, that contains a flattened representation of the
|
||||||
input document.
|
input document.
|
||||||
|
|
||||||
The `TESTNAME.expected` file format is as follows:
|
The `TESTNAME.expected` file format is as follows:
|
||||||
@@ -138,7 +144,9 @@ bool Reader::decodeNumber(Token& token) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Before submitting your code, ensure that you meet the versioning requirements above, follow the style guide of the file you are modifying (or the above rules for new files), and run clang format. Meson exposes clang format with the following command:
|
Before submitting your code, ensure that you meet the versioning requirements above, follow the style guide of the file you are modifying (or the above rules for new files), and run clang format. Meson exposes clang format with the following command:
|
||||||
|
|
||||||
```
|
```
|
||||||
ninja -v -C build-${LIB_TYPE}/ clang-format
|
ninja -v -C build-${LIB_TYPE}/ clang-format
|
||||||
```
|
```
|
||||||
|
|
||||||
|
For convenience, you can also run the `reformat.sh` script located in the root directory.
|
||||||
|
|
||||||
|
14
LICENSE
14
LICENSE
@@ -1,25 +1,25 @@
|
|||||||
The JsonCpp library's source code, including accompanying documentation,
|
The JsonCpp library's source code, including accompanying documentation,
|
||||||
tests and demonstration applications, are licensed under the following
|
tests and demonstration applications, are licensed under the following
|
||||||
conditions...
|
conditions...
|
||||||
|
|
||||||
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
Baptiste Lepilleur and The JsonCpp Authors explicitly disclaim copyright in all
|
||||||
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
jurisdictions which recognize such a disclaimer. In such jurisdictions,
|
||||||
this software is released into the Public Domain.
|
this software is released into the Public Domain.
|
||||||
|
|
||||||
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
|
||||||
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur and
|
||||||
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
The JsonCpp Authors, and is released under the terms of the MIT License (see below).
|
||||||
|
|
||||||
In jurisdictions which recognize Public Domain property, the user of this
|
In jurisdictions which recognize Public Domain property, the user of this
|
||||||
software may choose to accept it either as 1) Public Domain, 2) under the
|
software may choose to accept it either as 1) Public Domain, 2) under the
|
||||||
conditions of the MIT License (see below), or 3) under the terms of dual
|
conditions of the MIT License (see below), or 3) under the terms of dual
|
||||||
Public Domain/MIT License conditions described here, as they choose.
|
Public Domain/MIT License conditions described here, as they choose.
|
||||||
|
|
||||||
The MIT License is about as close to Public Domain as a license can get, and is
|
The MIT License is about as close to Public Domain as a license can get, and is
|
||||||
described in clear, concise terms at:
|
described in clear, concise terms at:
|
||||||
|
|
||||||
http://en.wikipedia.org/wiki/MIT_License
|
http://en.wikipedia.org/wiki/MIT_License
|
||||||
|
|
||||||
The full text of the MIT License follows:
|
The full text of the MIT License follows:
|
||||||
|
|
||||||
========================================================================
|
========================================================================
|
||||||
|
@@ -30,8 +30,14 @@ format to store user input files.
|
|||||||
|
|
||||||
* `1.y.z` is built with C++11.
|
* `1.y.z` is built with C++11.
|
||||||
* `0.y.z` can be used with older compilers.
|
* `0.y.z` can be used with older compilers.
|
||||||
|
* `00.11.z` can be used both in old and new compilers.
|
||||||
* Major versions maintain binary-compatibility.
|
* 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
|
## Using JsonCpp in your project
|
||||||
|
|
||||||
@@ -42,7 +48,7 @@ You can download and install JsonCpp using the [vcpkg](https://github.com/Micros
|
|||||||
cd vcpkg
|
cd vcpkg
|
||||||
./bootstrap-vcpkg.sh
|
./bootstrap-vcpkg.sh
|
||||||
./vcpkg integrate install
|
./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.
|
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.
|
||||||
|
|
||||||
|
17
SECURITY.md
Normal file
17
SECURITY.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
If you have discovered a security vulnerability in this project, please report it
|
||||||
|
privately. **Do not disclose it as a public issue.** This gives us time to work with you
|
||||||
|
to fix the issue before public exposure, reducing the chance that the exploit will be
|
||||||
|
used before a patch is released.
|
||||||
|
|
||||||
|
Please submit the report by filling out
|
||||||
|
[this form](https://github.com/open-source-parsers/jsoncpp/security/advisories/new).
|
||||||
|
|
||||||
|
Please provide the following information in your report:
|
||||||
|
|
||||||
|
- A description of the vulnerability and its impact
|
||||||
|
- How to reproduce the issue
|
||||||
|
|
||||||
|
This project is maintained by volunteers on a reasonable-effort basis. As such,
|
||||||
|
we ask that you give us 90 days to work on a fix before public exposure.
|
@@ -63,7 +63,7 @@ def amalgamate_source(source_top_dir=None,
|
|||||||
"""
|
"""
|
||||||
print("Amalgamating header...")
|
print("Amalgamating header...")
|
||||||
header = AmalgamationFile(source_top_dir)
|
header = AmalgamationFile(source_top_dir)
|
||||||
header.add_text("/// Json-cpp amalgamated header (http://jsoncpp.sourceforge.net/).")
|
header.add_text("/// Json-cpp amalgamated header (https://github.com/open-source-parsers/jsoncpp/).")
|
||||||
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
header.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
||||||
header.add_file("LICENSE", wrap_in_comment=True)
|
header.add_file("LICENSE", wrap_in_comment=True)
|
||||||
header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
|
header.add_text("#ifndef JSON_AMALGAMATED_H_INCLUDED")
|
||||||
@@ -90,7 +90,7 @@ def amalgamate_source(source_top_dir=None,
|
|||||||
forward_header_include_path = base + "-forwards" + ext
|
forward_header_include_path = base + "-forwards" + ext
|
||||||
print("Amalgamating forward header...")
|
print("Amalgamating forward header...")
|
||||||
header = AmalgamationFile(source_top_dir)
|
header = AmalgamationFile(source_top_dir)
|
||||||
header.add_text("/// Json-cpp amalgamated forward header (http://jsoncpp.sourceforge.net/).")
|
header.add_text("/// Json-cpp amalgamated forward header (https://github.com/open-source-parsers/jsoncpp/).")
|
||||||
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
|
header.add_text('/// It is intended to be used with #include "%s"' % forward_header_include_path)
|
||||||
header.add_text("/// This header provides forward declaration for all JsonCpp types.")
|
header.add_text("/// This header provides forward declaration for all JsonCpp types.")
|
||||||
header.add_file("LICENSE", wrap_in_comment=True)
|
header.add_file("LICENSE", wrap_in_comment=True)
|
||||||
@@ -99,6 +99,8 @@ def amalgamate_source(source_top_dir=None,
|
|||||||
header.add_text("/// If defined, indicates that the source file is amalgamated")
|
header.add_text("/// If defined, indicates that the source file is amalgamated")
|
||||||
header.add_text("/// to prevent private header inclusion.")
|
header.add_text("/// to prevent private header inclusion.")
|
||||||
header.add_text("#define JSON_IS_AMALGAMATION")
|
header.add_text("#define JSON_IS_AMALGAMATION")
|
||||||
|
header.add_file(os.path.join(INCLUDE_PATH, "version.h"))
|
||||||
|
header.add_file(os.path.join(INCLUDE_PATH, "allocator.h"))
|
||||||
header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
|
header.add_file(os.path.join(INCLUDE_PATH, "config.h"))
|
||||||
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
header.add_file(os.path.join(INCLUDE_PATH, "forwards.h"))
|
||||||
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
header.add_text("#endif //ifndef JSON_FORWARD_AMALGAMATED_H_INCLUDED")
|
||||||
@@ -110,7 +112,7 @@ def amalgamate_source(source_top_dir=None,
|
|||||||
|
|
||||||
print("Amalgamating source...")
|
print("Amalgamating source...")
|
||||||
source = AmalgamationFile(source_top_dir)
|
source = AmalgamationFile(source_top_dir)
|
||||||
source.add_text("/// Json-cpp amalgamated source (http://jsoncpp.sourceforge.net/).")
|
source.add_text("/// Json-cpp amalgamated source (https://github.com/open-source-parsers/jsoncpp/).")
|
||||||
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
source.add_text('/// It is intended to be used with #include "%s"' % header_include_path)
|
||||||
source.add_file("LICENSE", wrap_in_comment=True)
|
source.add_file("LICENSE", wrap_in_comment=True)
|
||||||
source.add_text("")
|
source.add_text("")
|
||||||
|
11
appveyor.yml
11
appveyor.yml
@@ -1,6 +1,7 @@
|
|||||||
clone_folder: c:\projects\jsoncpp
|
clone_folder: c:\projects\jsoncpp
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
- APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||||
CMAKE_GENERATOR: Visual Studio 14 2015
|
CMAKE_GENERATOR: Visual Studio 14 2015
|
||||||
@@ -13,11 +14,15 @@ environment:
|
|||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- cmake --version
|
- cmake --version
|
||||||
- cd c:\projects\jsoncpp
|
# The build script starts in root.
|
||||||
- cmake -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX:PATH=%CD:\=/%/install -DBUILD_SHARED_LIBS:BOOL=ON .
|
- set JSONCPP_FOLDER=%cd%
|
||||||
|
- set JSONCPP_BUILD_FOLDER=%JSONCPP_FOLDER%\build\release
|
||||||
|
- mkdir -p %JSONCPP_BUILD_FOLDER%
|
||||||
|
- cd %JSONCPP_BUILD_FOLDER%
|
||||||
|
- cmake -G "%CMAKE_GENERATOR%" -DCMAKE_INSTALL_PREFIX:PATH=%CD:\=/%/install -DBUILD_SHARED_LIBS:BOOL=ON %JSONCPP_FOLDER%
|
||||||
# Use ctest to make a dashboard build:
|
# Use ctest to make a dashboard build:
|
||||||
# - ctest -D Experimental(Start|Update|Configure|Build|Test|Coverage|MemCheck|Submit)
|
# - ctest -D Experimental(Start|Update|Configure|Build|Test|Coverage|MemCheck|Submit)
|
||||||
# NOTE: Testing on window is not yet finished:
|
# NOTE: Testing on windows is not yet finished:
|
||||||
# - ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalTest -D ExperimentalSubmit
|
# - ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalTest -D ExperimentalSubmit
|
||||||
- ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalSubmit
|
- ctest -C Release -D ExperimentalStart -D ExperimentalConfigure -D ExperimentalBuild -D ExperimentalSubmit
|
||||||
# Final step is to verify that installation succeeds
|
# Final step is to verify that installation succeeds
|
||||||
|
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,9 +1,11 @@
|
|||||||
# This is only for jsoncpp developers/contributors.
|
# This is only for jsoncpp developers/contributors.
|
||||||
# We use this to sign releases, generate documentation, etc.
|
# We use this to sign releases, generate documentation, etc.
|
||||||
VER?=$(shell cat version.txt)
|
VER?=$(shell cat version)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@echo "VER=${VER}"
|
@echo "VER=${VER}"
|
||||||
|
update-version:
|
||||||
|
perl get_version.pl meson.build >| version
|
||||||
sign: jsoncpp-${VER}.tar.gz
|
sign: jsoncpp-${VER}.tar.gz
|
||||||
gpg --armor --detach-sign $<
|
gpg --armor --detach-sign $<
|
||||||
gpg --verify $<.asc
|
gpg --verify $<.asc
|
||||||
|
@@ -146,7 +146,7 @@ def glob(dir_path,
|
|||||||
entry_type = is_file and FILE_LINK or DIR_LINK
|
entry_type = is_file and FILE_LINK or DIR_LINK
|
||||||
else:
|
else:
|
||||||
entry_type = is_file and FILE or DIR
|
entry_type = is_file and FILE or DIR
|
||||||
## print '=> type: %d' % entry_type,
|
## print '=> type: %d' % entry_type,
|
||||||
if (entry_type & entry_type_filter) != 0:
|
if (entry_type & entry_type_filter) != 0:
|
||||||
## print ' => KEEP'
|
## print ' => KEEP'
|
||||||
yield os.path.join(dir_path, entry)
|
yield os.path.join(dir_path, entry)
|
||||||
|
@@ -9,7 +9,7 @@ import shutil
|
|||||||
import string
|
import string
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import cgi
|
import html
|
||||||
|
|
||||||
class BuildDesc:
|
class BuildDesc:
|
||||||
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
|
def __init__(self, prepend_envs=None, variables=None, build_type=None, generator=None):
|
||||||
@@ -195,12 +195,12 @@ def generate_html_report(html_report_path, builds):
|
|||||||
for variable in variables:
|
for variable in variables:
|
||||||
build_types = sorted(build_types_by_variable[variable])
|
build_types = sorted(build_types_by_variable[variable])
|
||||||
nb_build_type = len(build_types_by_variable[variable])
|
nb_build_type = len(build_types_by_variable[variable])
|
||||||
th_vars.append('<th colspan="%d">%s</th>' % (nb_build_type, cgi.escape(' '.join(variable))))
|
th_vars.append('<th colspan="%d">%s</th>' % (nb_build_type, html.escape(' '.join(variable))))
|
||||||
for build_type in build_types:
|
for build_type in build_types:
|
||||||
th_build_types.append('<th>%s</th>' % cgi.escape(build_type))
|
th_build_types.append('<th>%s</th>' % html.escape(build_type))
|
||||||
tr_builds = []
|
tr_builds = []
|
||||||
for generator in sorted(builds_by_generator):
|
for generator in sorted(builds_by_generator):
|
||||||
tds = [ '<td>%s</td>\n' % cgi.escape(generator) ]
|
tds = [ '<td>%s</td>\n' % html.escape(generator) ]
|
||||||
for variable in variables:
|
for variable in variables:
|
||||||
build_types = sorted(build_types_by_variable[variable])
|
build_types = sorted(build_types_by_variable[variable])
|
||||||
for build_type in build_types:
|
for build_type in build_types:
|
||||||
|
@@ -32,8 +32,8 @@ def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'):
|
|||||||
if verbose:
|
if verbose:
|
||||||
print(is_dry_run and ' NEED FIX' or ' FIXED')
|
print(is_dry_run and ' NEED FIX' or ' FIXED')
|
||||||
return True
|
return True
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
##
|
##
|
||||||
##def _do_fix(is_dry_run = True):
|
##def _do_fix(is_dry_run = True):
|
||||||
## from waftools import antglob
|
## from waftools import antglob
|
||||||
|
@@ -20,7 +20,7 @@ def update_license(path, dry_run, show_diff):
|
|||||||
dry_run: if True, just print the path of the file that would be updated,
|
dry_run: if True, just print the path of the file that would be updated,
|
||||||
but don't change it.
|
but don't change it.
|
||||||
show_diff: if True, print the path of the file that would be modified,
|
show_diff: if True, print the path of the file that would be modified,
|
||||||
as well as the change made to the file.
|
as well as the change made to the file.
|
||||||
"""
|
"""
|
||||||
with open(path, 'rt') as fin:
|
with open(path, 'rt') as fin:
|
||||||
original_text = fin.read().replace('\r\n','\n')
|
original_text = fin.read().replace('\r\n','\n')
|
||||||
@@ -51,7 +51,7 @@ def update_license_in_source_directories(source_dirs, dry_run, show_diff):
|
|||||||
dry_run: if True, just print the path of the file that would be updated,
|
dry_run: if True, just print the path of the file that would be updated,
|
||||||
but don't change it.
|
but don't change it.
|
||||||
show_diff: if True, print the path of the file that would be modified,
|
show_diff: if True, print the path of the file that would be modified,
|
||||||
as well as the change made to the file.
|
as well as the change made to the file.
|
||||||
"""
|
"""
|
||||||
from devtools import antglob
|
from devtools import antglob
|
||||||
prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
|
prune_dirs = antglob.prune_dirs + 'scons-local* ./build* ./libs ./dist'
|
||||||
|
@@ -46,7 +46,7 @@ def do_subst_in_file(targetfile, sourcefile, dict):
|
|||||||
with open(sourcefile, 'r') as f:
|
with open(sourcefile, 'r') as f:
|
||||||
contents = f.read()
|
contents = f.read()
|
||||||
for (k,v) in list(dict.items()):
|
for (k,v) in list(dict.items()):
|
||||||
v = v.replace('\\','\\\\')
|
v = v.replace('\\','\\\\')
|
||||||
contents = re.sub(k, v, contents)
|
contents = re.sub(k, v, contents)
|
||||||
with open(targetfile, 'w') as f:
|
with open(targetfile, 'w') as f:
|
||||||
f.write(contents)
|
f.write(contents)
|
||||||
@@ -158,7 +158,7 @@ def main():
|
|||||||
Generates doxygen documentation in build/doxygen.
|
Generates doxygen documentation in build/doxygen.
|
||||||
Optionally makes a tarball of the documentation to dist/.
|
Optionally makes a tarball of the documentation to dist/.
|
||||||
|
|
||||||
Must be started in the project top directory.
|
Must be started in the project top directory.
|
||||||
"""
|
"""
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
parser = OptionParser(usage=usage)
|
parser = OptionParser(usage=usage)
|
||||||
|
@@ -1,29 +1,27 @@
|
|||||||
#vim: et ts =4 sts = 4 sw = 4 tw = 0
|
#vim: et ts =4 sts = 4 sw = 4 tw = 0
|
||||||
cmake_minimum_required(VERSION 3.1)
|
|
||||||
|
|
||||||
set(EXAMPLES
|
set(EXAMPLES
|
||||||
readFromString
|
readFromString
|
||||||
readFromStream
|
readFromStream
|
||||||
stringWrite
|
stringWrite
|
||||||
streamWrite
|
streamWrite
|
||||||
)
|
)
|
||||||
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
|
add_definitions(-D_GLIBCXX_USE_CXX11_ABI)
|
||||||
set_property(DIRECTORY PROPERTY COMPILE_OPTIONS ${EXTRA_CXX_FLAGS})
|
|
||||||
|
|
||||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra ")
|
add_compile_options(-Wall -Wextra)
|
||||||
else()
|
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||||
add_definitions(
|
add_definitions(
|
||||||
-D_SCL_SECURE_NO_WARNINGS
|
-D_SCL_SECURE_NO_WARNINGS
|
||||||
-D_CRT_SECURE_NO_WARNINGS
|
-D_CRT_SECURE_NO_WARNINGS
|
||||||
-D_WIN32_WINNT=0x601
|
-D_WIN32_WINNT=0x601
|
||||||
-D_WINSOCK_DEPRECATED_NO_WARNINGS)
|
-D_WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
foreach (example ${EXAMPLES})
|
foreach(example ${EXAMPLES})
|
||||||
add_executable(${example} ${example}/${example}.cpp)
|
add_executable(${example} ${example}/${example}.cpp)
|
||||||
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
target_include_directories(${example} PUBLIC ${CMAKE_SOURCE_DIR}/include)
|
||||||
target_link_libraries(${example} jsoncpp_lib)
|
target_link_libraries(${example} jsoncpp_lib)
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
add_custom_target(examples ALL DEPENDS ${EXAMPLES})
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
***NOTE***
|
***NOTE***
|
||||||
|
|
||||||
If you get linker errors about undefined references to symbols that involve types in the `std::__cxx11` namespace or the tag
|
If you get linker errors about undefined references to symbols that involve types in the `std::__cxx11` namespace or the tag
|
||||||
`[abi:cxx11]` then it probably indicates that you are trying to link together object files that were compiled with different
|
`[abi:cxx11]` then it probably indicates that you are trying to link together object files that were compiled with different
|
||||||
values for the _GLIBCXX_USE_CXX11_ABI marco. This commonly happens when linking to a third-party library that was compiled with
|
values for the _GLIBCXX_USE_CXX11_ABI marco. This commonly happens when linking to a third-party library that was compiled with
|
||||||
an older version of GCC. If the third-party library cannot be rebuilt with the new ABI, then you need to recompile your code with
|
an older version of GCC. If the third-party library cannot be rebuilt with the new ABI, then you need to recompile your code with
|
||||||
the old ABI,just like:
|
the old ABI,just like:
|
||||||
**g++ stringWrite.cpp -ljsoncpp -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -o stringWrite**
|
**g++ stringWrite.cpp -ljsoncpp -std=c++11 -D_GLIBCXX_USE_CXX11_ABI=0 -o stringWrite**
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
/**
|
/**
|
||||||
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
* \brief Parse a raw string into Value object using the CharReaderBuilder
|
||||||
* class, or the legacy Reader class.
|
* class, or the legacy Reader class.
|
||||||
@@ -11,7 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
int main() {
|
int main() {
|
||||||
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
|
||||||
const int rawJsonLength = static_cast<int>(rawJson.length());
|
const auto rawJsonLength = static_cast<int>(rawJson.length());
|
||||||
constexpr bool shouldUseOldWay = false;
|
constexpr bool shouldUseOldWay = false;
|
||||||
JSONCPP_STRING err;
|
JSONCPP_STRING err;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
@@ -24,7 +25,7 @@ int main() {
|
|||||||
const std::unique_ptr<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,
|
if (!reader->parse(rawJson.c_str(), rawJson.c_str() + rawJsonLength, &root,
|
||||||
&err)) {
|
&err)) {
|
||||||
std::cout << "error" << std::endl;
|
std::cout << "error: " << err << std::endl;
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
#include "json/json.h"
|
#include "json/json.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <memory>
|
||||||
/** \brief Write the Value object to a stream.
|
/** \brief Write the Value object to a stream.
|
||||||
* Example Usage:
|
* Example Usage:
|
||||||
* $g++ streamWrite.cpp -ljsoncpp -std=c++11 -o streamWrite
|
* $g++ streamWrite.cpp -ljsoncpp -std=c++11 -o streamWrite
|
||||||
|
5
get_version.pl
Normal file
5
get_version.pl
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
while (<>) {
|
||||||
|
if (/version : '(.+)',/) {
|
||||||
|
print "$1";
|
||||||
|
}
|
||||||
|
}
|
9
include/PreventInBuildInstalls.cmake
Normal file
9
include/PreventInBuildInstalls.cmake
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
string(TOLOWER "${CMAKE_INSTALL_PREFIX}" _PREFIX)
|
||||||
|
string(TOLOWER "${ITK_BINARY_DIR}" _BUILD)
|
||||||
|
if("${_PREFIX}" STREQUAL "${_BUILD}")
|
||||||
|
message(FATAL_ERROR
|
||||||
|
"The current CMAKE_INSTALL_PREFIX points at the build tree:\n"
|
||||||
|
" ${CMAKE_INSTALL_PREFIX}\n"
|
||||||
|
"This is not supported."
|
||||||
|
)
|
||||||
|
endif()
|
45
include/PreventInSourceBuilds.cmake
Normal file
45
include/PreventInSourceBuilds.cmake
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#
|
||||||
|
# This function will prevent in-source builds
|
||||||
|
function(AssureOutOfSourceBuilds)
|
||||||
|
# make sure the user doesn't play dirty with symlinks
|
||||||
|
get_filename_component(srcdir "${CMAKE_CURRENT_SOURCE_DIR}" REALPATH)
|
||||||
|
get_filename_component(bindir "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
|
||||||
|
|
||||||
|
# disallow in-source builds
|
||||||
|
if("${srcdir}" STREQUAL "${bindir}")
|
||||||
|
message("######################################################")
|
||||||
|
message("# jsoncpp should not be configured & built in the jsoncpp source directory")
|
||||||
|
message("# You must run cmake in a build directory.")
|
||||||
|
message("# For example:")
|
||||||
|
message("# mkdir jsoncpp-Sandbox ; cd jsoncpp-sandbox")
|
||||||
|
message("# git clone https://github.com/open-source-parsers/jsoncpp.git # or download & unpack the source tarball")
|
||||||
|
message("# mkdir jsoncpp-build")
|
||||||
|
message("# this will create the following directory structure")
|
||||||
|
message("#")
|
||||||
|
message("# jsoncpp-Sandbox")
|
||||||
|
message("# +--jsoncpp")
|
||||||
|
message("# +--jsoncpp-build")
|
||||||
|
message("#")
|
||||||
|
message("# Then you can proceed to configure and build")
|
||||||
|
message("# by using the following commands")
|
||||||
|
message("#")
|
||||||
|
message("# cd jsoncpp-build")
|
||||||
|
message("# cmake ../jsoncpp # or ccmake, or cmake-gui ")
|
||||||
|
message("# make")
|
||||||
|
message("#")
|
||||||
|
message("# NOTE: Given that you already tried to make an in-source build")
|
||||||
|
message("# CMake have already created several files & directories")
|
||||||
|
message("# in your source tree. run 'git status' to find them and")
|
||||||
|
message("# remove them by doing:")
|
||||||
|
message("#")
|
||||||
|
message("# cd jsoncpp-Sandbox/jsoncpp")
|
||||||
|
message("# git clean -n -d")
|
||||||
|
message("# git clean -f -d")
|
||||||
|
message("# git checkout --")
|
||||||
|
message("#")
|
||||||
|
message("######################################################")
|
||||||
|
message(FATAL_ERROR "Quitting configuration")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
AssureOutOfSourceBuilds()
|
@@ -3,13 +3,15 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#ifndef JSON_ALLOCATOR_H_INCLUDED
|
||||||
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#define JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push)
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
template <typename T> class SecureAllocator {
|
template <typename T> class SecureAllocator {
|
||||||
@@ -35,11 +37,18 @@ public:
|
|||||||
* Release memory which was allocated for N items at pointer P.
|
* Release memory which was allocated for N items at pointer P.
|
||||||
*
|
*
|
||||||
* The memory block is filled with zeroes before being released.
|
* The memory block is filled with zeroes before being released.
|
||||||
* The pointer argument is tagged as "volatile" to prevent the
|
|
||||||
* compiler optimizing out this critical step.
|
|
||||||
*/
|
*/
|
||||||
void deallocate(volatile pointer p, size_type n) {
|
void deallocate(pointer p, size_type n) {
|
||||||
std::memset(p, 0, n * sizeof(T));
|
// These constructs will not be removed by the compiler during optimization,
|
||||||
|
// unlike memset.
|
||||||
|
#if defined(HAVE_MEMSET_S)
|
||||||
|
memset_s(p, n * sizeof(T), 0, n * sizeof(T));
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
RtlSecureZeroMemory(p, n * sizeof(T));
|
||||||
|
#else
|
||||||
|
std::fill_n(reinterpret_cast<volatile unsigned char*>(p), n, 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// free using "global operator delete"
|
// free using "global operator delete"
|
||||||
::operator delete(p);
|
::operator delete(p);
|
||||||
}
|
}
|
||||||
@@ -69,7 +78,9 @@ public:
|
|||||||
// Boilerplate
|
// Boilerplate
|
||||||
SecureAllocator() {}
|
SecureAllocator() {}
|
||||||
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
template <typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
template <typename U> struct rebind { using other = SecureAllocator<U>; };
|
template <typename U> struct rebind {
|
||||||
|
using other = SecureAllocator<U>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
@@ -86,4 +97,4 @@ bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
#endif // JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#ifndef JSON_ASSERTIONS_H_INCLUDED
|
||||||
#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#define JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@@ -21,19 +21,19 @@
|
|||||||
|
|
||||||
// @todo <= add detail about condition in exception
|
// @todo <= add detail about condition in exception
|
||||||
#define JSON_ASSERT(condition) \
|
#define JSON_ASSERT(condition) \
|
||||||
{ \
|
do { \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
Json::throwLogicError("assert json failed"); \
|
Json::throwLogicError("assert json failed"); \
|
||||||
} \
|
} \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
#define JSON_FAIL_MESSAGE(message) \
|
#define JSON_FAIL_MESSAGE(message) \
|
||||||
{ \
|
do { \
|
||||||
OStringStream oss; \
|
OStringStream oss; \
|
||||||
oss << message; \
|
oss << message; \
|
||||||
Json::throwLogicError(oss.str()); \
|
Json::throwLogicError(oss.str()); \
|
||||||
abort(); \
|
abort(); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
#else // JSON_USE_EXCEPTION
|
#else // JSON_USE_EXCEPTION
|
||||||
|
|
||||||
@@ -52,8 +52,10 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define JSON_ASSERT_MESSAGE(condition, message) \
|
#define JSON_ASSERT_MESSAGE(condition, message) \
|
||||||
if (!(condition)) { \
|
do { \
|
||||||
JSON_FAIL_MESSAGE(message); \
|
if (!(condition)) { \
|
||||||
}
|
JSON_FAIL_MESSAGE(message); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
|
#endif // JSON_ASSERTIONS_H_INCLUDED
|
||||||
|
@@ -1,25 +0,0 @@
|
|||||||
// Copyright 2007-2010 Baptiste Lepilleur and The JsonCpp Authors
|
|
||||||
// Distributed under MIT license, or public domain if desired and
|
|
||||||
// recognized in your jurisdiction.
|
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
|
||||||
|
|
||||||
#ifndef JSON_AUTOLINK_H_INCLUDED
|
|
||||||
#define JSON_AUTOLINK_H_INCLUDED
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#ifdef JSON_IN_CPPTL
|
|
||||||
#include <cpptl/cpptl_autolink.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(JSON_NO_AUTOLINK) && !defined(JSON_DLL_BUILD) && \
|
|
||||||
!defined(JSON_IN_CPPTL)
|
|
||||||
#define CPPTL_AUTOLINK_NAME "json"
|
|
||||||
#undef CPPTL_AUTOLINK_DLL
|
|
||||||
#ifdef JSON_DLL
|
|
||||||
#define CPPTL_AUTOLINK_DLL
|
|
||||||
#endif
|
|
||||||
#include "autolink.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // JSON_AUTOLINK_H_INCLUDED
|
|
@@ -14,16 +14,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
/// If defined, indicates that json library is embedded in CppTL library.
|
|
||||||
//# define JSON_IN_CPPTL 1
|
|
||||||
|
|
||||||
/// If defined, indicates that json may leverage CppTL library
|
|
||||||
//# define JSON_USE_CPPTL 1
|
|
||||||
/// If defined, indicates that cpptl vector based map should be used instead of
|
|
||||||
/// std::map
|
|
||||||
/// as Value container.
|
|
||||||
//# define JSON_USE_CPPTL_SMALLMAP 1
|
|
||||||
|
|
||||||
// If non-zero, the library uses exceptions to report bad input instead of C
|
// If non-zero, the library uses exceptions to report bad input instead of C
|
||||||
// assertion macros. The default is to use exceptions.
|
// assertion macros. The default is to use exceptions.
|
||||||
#ifndef JSON_USE_EXCEPTION
|
#ifndef JSON_USE_EXCEPTION
|
||||||
@@ -40,28 +30,22 @@
|
|||||||
/// Remarks: it is automatically defined in the generated amalgamated header.
|
/// Remarks: it is automatically defined in the generated amalgamated header.
|
||||||
// #define JSON_IS_AMALGAMATION
|
// #define JSON_IS_AMALGAMATION
|
||||||
|
|
||||||
#ifdef JSON_IN_CPPTL
|
// Export macros for DLL visibility
|
||||||
#include <cpptl/config.h>
|
#if defined(JSON_DLL_BUILD)
|
||||||
#ifndef JSON_USE_CPPTL
|
|
||||||
#define JSON_USE_CPPTL 1
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef JSON_IN_CPPTL
|
|
||||||
#define JSON_API CPPTL_API
|
|
||||||
#elif defined(JSON_DLL_BUILD)
|
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllexport)
|
#define JSON_API __declspec(dllexport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#elif defined(__GNUC__) || defined(__clang__)
|
#elif defined(__GNUC__) || defined(__clang__)
|
||||||
#define JSON_API __attribute__((visibility("default")))
|
#define JSON_API __attribute__((visibility("default")))
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
|
|
||||||
#elif defined(JSON_DLL)
|
#elif defined(JSON_DLL)
|
||||||
#if defined(_MSC_VER) || defined(__MINGW32__)
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
#define JSON_API __declspec(dllimport)
|
#define JSON_API __declspec(dllimport)
|
||||||
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
#endif // ifdef JSON_IN_CPPTL
|
#endif // ifdef JSON_DLL_BUILD
|
||||||
|
|
||||||
#if !defined(JSON_API)
|
#if !defined(JSON_API)
|
||||||
#define JSON_API
|
#define JSON_API
|
||||||
#endif
|
#endif
|
||||||
@@ -90,20 +74,6 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
// C++11 should be used directly in JSONCPP.
|
// C++11 should be used directly in JSONCPP.
|
||||||
#define JSONCPP_OVERRIDE override
|
#define JSONCPP_OVERRIDE override
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
#define JSONCPP_NOEXCEPT noexcept
|
|
||||||
#define JSONCPP_OP_EXPLICIT explicit
|
|
||||||
#elif defined(_MSC_VER) && _MSC_VER < 1900
|
|
||||||
#define JSONCPP_NOEXCEPT throw()
|
|
||||||
#define JSONCPP_OP_EXPLICIT explicit
|
|
||||||
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
|
||||||
#define JSONCPP_NOEXCEPT noexcept
|
|
||||||
#define JSONCPP_OP_EXPLICIT explicit
|
|
||||||
#else
|
|
||||||
#define JSONCPP_NOEXCEPT throw()
|
|
||||||
#define JSONCPP_OP_EXPLICIT
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
#if __has_extension(attribute_deprecated_with_message)
|
#if __has_extension(attribute_deprecated_with_message)
|
||||||
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||||
@@ -135,29 +105,29 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
|
|||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
typedef int Int;
|
using Int = int;
|
||||||
typedef unsigned int UInt;
|
using UInt = unsigned int;
|
||||||
#if defined(JSON_NO_INT64)
|
#if defined(JSON_NO_INT64)
|
||||||
typedef int LargestInt;
|
using LargestInt = int;
|
||||||
typedef unsigned int LargestUInt;
|
using LargestUInt = unsigned int;
|
||||||
#undef JSON_HAS_INT64
|
#undef JSON_HAS_INT64
|
||||||
#else // if defined(JSON_NO_INT64)
|
#else // if defined(JSON_NO_INT64)
|
||||||
// For Microsoft Visual use specific types as long long is not supported
|
// For Microsoft Visual use specific types as long long is not supported
|
||||||
#if defined(_MSC_VER) // Microsoft Visual Studio
|
#if defined(_MSC_VER) // Microsoft Visual Studio
|
||||||
typedef __int64 Int64;
|
using Int64 = __int64;
|
||||||
typedef unsigned __int64 UInt64;
|
using UInt64 = unsigned __int64;
|
||||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
typedef int64_t Int64;
|
using Int64 = int64_t;
|
||||||
typedef uint64_t UInt64;
|
using UInt64 = uint64_t;
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
typedef Int64 LargestInt;
|
using LargestInt = Int64;
|
||||||
typedef UInt64 LargestUInt;
|
using LargestUInt = UInt64;
|
||||||
#define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
#endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
using Allocator =
|
using Allocator =
|
||||||
typename std::conditional<JSONCPP_USING_SECURE_MEMORY, SecureAllocator<T>,
|
typename std::conditional<JSONCPP_USE_SECURE_MEMORY, SecureAllocator<T>,
|
||||||
std::allocator<T>>::type;
|
std::allocator<T>>::type;
|
||||||
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
using String = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
|
||||||
using IStringStream =
|
using IStringStream =
|
||||||
|
@@ -29,7 +29,7 @@ class CharReaderBuilder;
|
|||||||
class Features;
|
class Features;
|
||||||
|
|
||||||
// value.h
|
// value.h
|
||||||
typedef unsigned int ArrayIndex;
|
using ArrayIndex = unsigned int;
|
||||||
class StaticString;
|
class StaticString;
|
||||||
class Path;
|
class Path;
|
||||||
class PathArgument;
|
class PathArgument;
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
#ifndef JSON_JSON_H_INCLUDED
|
#ifndef JSON_JSON_H_INCLUDED
|
||||||
#define JSON_JSON_H_INCLUDED
|
#define JSON_JSON_H_INCLUDED
|
||||||
|
|
||||||
#include "autolink.h"
|
#include "config.h"
|
||||||
#include "json_features.h"
|
#include "json_features.h"
|
||||||
#include "reader.h"
|
#include "reader.h"
|
||||||
#include "value.h"
|
#include "value.h"
|
||||||
|
@@ -3,14 +3,15 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
|
#ifndef JSON_FEATURES_H_INCLUDED
|
||||||
#define CPPTL_JSON_FEATURES_H_INCLUDED
|
#define JSON_FEATURES_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push)
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
@@ -58,4 +59,4 @@ public:
|
|||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
#endif // JSON_FEATURES_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_READER_H_INCLUDED
|
#ifndef JSON_READER_H_INCLUDED
|
||||||
#define CPPTL_JSON_READER_H_INCLUDED
|
#define JSON_READER_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "json_features.h"
|
#include "json_features.h"
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push)
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
@@ -33,11 +34,10 @@ namespace Json {
|
|||||||
* \deprecated Use CharReader and CharReaderBuilder.
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class JSONCPP_DEPRECATED(
|
class JSON_API Reader {
|
||||||
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
|
|
||||||
public:
|
public:
|
||||||
typedef char Char;
|
using Char = char;
|
||||||
typedef const Char* Location;
|
using Location = const Char*;
|
||||||
|
|
||||||
/** \brief An error tagged with where in the JSON text it was encountered.
|
/** \brief An error tagged with where in the JSON text it was encountered.
|
||||||
*
|
*
|
||||||
@@ -51,13 +51,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing all features for parsing.
|
/** \brief Constructs a Reader allowing all features for parsing.
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
|
||||||
Reader();
|
Reader();
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
/** \brief Constructs a Reader allowing the specified feature set for parsing.
|
||||||
|
* \deprecated Use CharReader and CharReaderBuilder.
|
||||||
*/
|
*/
|
||||||
JSONCPP_DEPRECATED("Use CharReader and CharReaderBuilder instead")
|
|
||||||
Reader(const Features& features);
|
Reader(const Features& features);
|
||||||
|
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
@@ -187,9 +187,10 @@ private:
|
|||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::deque<ErrorInfo> Errors;
|
using Errors = std::deque<ErrorInfo>;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
|
bool readTokenSkippingComments(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
bool match(const Char* pattern, int patternLength);
|
bool match(const Char* pattern, int patternLength);
|
||||||
bool readComment();
|
bool readComment();
|
||||||
@@ -221,12 +222,11 @@ private:
|
|||||||
int& column) const;
|
int& column) const;
|
||||||
String getLocationLineAndColumn(Location location) const;
|
String getLocationLineAndColumn(Location location) const;
|
||||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
void skipCommentTokens(Token& token);
|
|
||||||
|
|
||||||
static bool containsNewLine(Location begin, Location end);
|
static bool containsNewLine(Location begin, Location end);
|
||||||
static String normalizeEOL(Location begin, Location end);
|
static String normalizeEOL(Location begin, Location end);
|
||||||
|
|
||||||
typedef std::stack<Value*> Nodes;
|
using Nodes = std::stack<Value*>;
|
||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
String document_;
|
String document_;
|
||||||
@@ -244,6 +244,12 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API CharReader {
|
class JSON_API CharReader {
|
||||||
public:
|
public:
|
||||||
|
struct JSON_API StructuredError {
|
||||||
|
ptrdiff_t offset_start;
|
||||||
|
ptrdiff_t offset_limit;
|
||||||
|
String message;
|
||||||
|
};
|
||||||
|
|
||||||
virtual ~CharReader() = default;
|
virtual ~CharReader() = default;
|
||||||
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
/** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
|
||||||
* document. The document must be a UTF-8 encoded string containing the
|
* document. The document must be a UTF-8 encoded string containing the
|
||||||
@@ -262,7 +268,12 @@ public:
|
|||||||
* error occurred.
|
* error occurred.
|
||||||
*/
|
*/
|
||||||
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
String* errs) = 0;
|
String* errs);
|
||||||
|
|
||||||
|
/** \brief Returns a vector of structured errors encountered while parsing.
|
||||||
|
* Each parse call resets the stored list of errors.
|
||||||
|
*/
|
||||||
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
class JSON_API Factory {
|
class JSON_API Factory {
|
||||||
public:
|
public:
|
||||||
@@ -272,7 +283,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual CharReader* newCharReader() const = 0;
|
virtual CharReader* newCharReader() const = 0;
|
||||||
}; // Factory
|
}; // Factory
|
||||||
}; // CharReader
|
|
||||||
|
protected:
|
||||||
|
class Impl {
|
||||||
|
public:
|
||||||
|
virtual ~Impl() = default;
|
||||||
|
virtual bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) = 0;
|
||||||
|
virtual std::vector<StructuredError> getStructuredErrors() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit CharReader(std::unique_ptr<Impl> impl) : _impl(std::move(impl)) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<Impl> _impl;
|
||||||
|
}; // CharReader
|
||||||
|
|
||||||
/** \brief Build a CharReader implementation.
|
/** \brief Build a CharReader implementation.
|
||||||
*
|
*
|
||||||
@@ -299,6 +324,8 @@ public:
|
|||||||
* if allowComments is false.
|
* if allowComments is false.
|
||||||
* - `"allowComments": false or true`
|
* - `"allowComments": false or true`
|
||||||
* - true if comments are allowed.
|
* - true if comments are allowed.
|
||||||
|
* - `"allowTrailingCommas": false or true`
|
||||||
|
* - true if trailing commas in objects and arrays are allowed.
|
||||||
* - `"strictRoot": false or true`
|
* - `"strictRoot": false or true`
|
||||||
* - true if root must be either an array or an object value
|
* - true if root must be either an array or an object value
|
||||||
* - `"allowDroppedNullPlaceholders": false or true`
|
* - `"allowDroppedNullPlaceholders": false or true`
|
||||||
@@ -322,6 +349,9 @@ public:
|
|||||||
* - `"allowSpecialFloats": false or true`
|
* - `"allowSpecialFloats": false or true`
|
||||||
* - If true, special float values (NaNs and infinities) are allowed and
|
* - If true, special float values (NaNs and infinities) are allowed and
|
||||||
* their values are lossfree restorable.
|
* their values are lossfree restorable.
|
||||||
|
* - `"skipBom": false or true`
|
||||||
|
* - If true, if the input starts with the Unicode byte order mark (BOM),
|
||||||
|
* it is skipped.
|
||||||
*
|
*
|
||||||
* You can examine 'settings_` yourself to see the defaults. You can also
|
* You can examine 'settings_` yourself to see the defaults. You can also
|
||||||
* write and read them just like any JSON Value.
|
* write and read them just like any JSON Value.
|
||||||
@@ -355,6 +385,12 @@ public:
|
|||||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
*/
|
*/
|
||||||
static void strictMode(Json::Value* settings);
|
static void strictMode(Json::Value* settings);
|
||||||
|
/** ECMA-404 mode.
|
||||||
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
|
* \remark Defaults:
|
||||||
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderECMA404Mode
|
||||||
|
*/
|
||||||
|
static void ecma404Mode(Json::Value* settings);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Consume entire stream and use its begin/end.
|
/** Consume entire stream and use its begin/end.
|
||||||
@@ -398,4 +434,4 @@ JSON_API IStream& operator>>(IStream&, Value&);
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_READER_H_INCLUDED
|
#endif // JSON_READER_H_INCLUDED
|
||||||
|
@@ -3,8 +3,8 @@
|
|||||||
// recognized in your jurisdiction.
|
// recognized in your jurisdiction.
|
||||||
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
|
||||||
|
|
||||||
#ifndef CPPTL_JSON_H_INCLUDED
|
#ifndef JSON_VALUE_H_INCLUDED
|
||||||
#define CPPTL_JSON_H_INCLUDED
|
#define JSON_VALUE_H_INCLUDED
|
||||||
|
|
||||||
#if !defined(JSON_IS_AMALGAMATION)
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
@@ -21,29 +21,40 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Support for '= delete' with template declarations was a late addition
|
||||||
|
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
|
||||||
|
// even though these declare themselves to be c++11 compilers.
|
||||||
|
#if !defined(JSONCPP_TEMPLATE_DELETE)
|
||||||
|
#if defined(__clang__) && defined(__apple_build_version__)
|
||||||
|
#if __apple_build_version__ <= 8000042
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#endif
|
||||||
|
#elif defined(__clang__)
|
||||||
|
#if __clang_major__ == 3 && __clang_minor__ <= 8
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#if !defined(JSONCPP_TEMPLATE_DELETE)
|
||||||
|
#define JSONCPP_TEMPLATE_DELETE = delete
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#ifndef JSON_USE_CPPTL_SMALLMAP
|
|
||||||
#include <map>
|
|
||||||
#else
|
|
||||||
#include <cpptl/smallmap.h>
|
|
||||||
#endif
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
#include <cpptl/forwards.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
// Disable warning C4251: <data member>: <type> needs to have dll-interface to
|
||||||
// be used by...
|
// be used by...
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251 4275)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push)
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
/** \brief JSON (JavaScript Object Notation).
|
/** \brief JSON (JavaScript Object Notation).
|
||||||
*/
|
*/
|
||||||
@@ -57,8 +68,8 @@ namespace Json {
|
|||||||
class JSON_API Exception : public std::exception {
|
class JSON_API Exception : public std::exception {
|
||||||
public:
|
public:
|
||||||
Exception(String msg);
|
Exception(String msg);
|
||||||
~Exception() JSONCPP_NOEXCEPT override;
|
~Exception() noexcept override;
|
||||||
char const* what() const JSONCPP_NOEXCEPT override;
|
char const* what() const noexcept override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
String msg_;
|
String msg_;
|
||||||
@@ -120,11 +131,6 @@ enum PrecisionType {
|
|||||||
decimalPlaces ///< we set max number of digits after "." in string
|
decimalPlaces ///< we set max number of digits after "." in string
|
||||||
};
|
};
|
||||||
|
|
||||||
//# ifdef JSON_USE_CPPTL
|
|
||||||
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
|
|
||||||
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
|
|
||||||
//# endif
|
|
||||||
|
|
||||||
/** \brief Lightweight wrapper to tag static string.
|
/** \brief Lightweight wrapper to tag static string.
|
||||||
*
|
*
|
||||||
* Value constructor and objectValue member assignment takes advantage of the
|
* Value constructor and objectValue member assignment takes advantage of the
|
||||||
@@ -189,21 +195,21 @@ class JSON_API Value {
|
|||||||
friend class ValueIteratorBase;
|
friend class ValueIteratorBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef std::vector<String> Members;
|
using Members = std::vector<String>;
|
||||||
typedef ValueIterator iterator;
|
using iterator = ValueIterator;
|
||||||
typedef ValueConstIterator const_iterator;
|
using const_iterator = ValueConstIterator;
|
||||||
typedef Json::UInt UInt;
|
using UInt = Json::UInt;
|
||||||
typedef Json::Int Int;
|
using Int = Json::Int;
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
typedef Json::UInt64 UInt64;
|
using UInt64 = Json::UInt64;
|
||||||
typedef Json::Int64 Int64;
|
using Int64 = Json::Int64;
|
||||||
#endif // defined(JSON_HAS_INT64)
|
#endif // defined(JSON_HAS_INT64)
|
||||||
typedef Json::LargestInt LargestInt;
|
using LargestInt = Json::LargestInt;
|
||||||
typedef Json::LargestUInt LargestUInt;
|
using LargestUInt = Json::LargestUInt;
|
||||||
typedef Json::ArrayIndex ArrayIndex;
|
using ArrayIndex = Json::ArrayIndex;
|
||||||
|
|
||||||
// Required for boost integration, e. g. BOOST_TEST
|
// Required for boost integration, e. g. BOOST_TEST
|
||||||
typedef std::string value_type;
|
using value_type = std::string;
|
||||||
|
|
||||||
#if JSON_USE_NULLREF
|
#if JSON_USE_NULLREF
|
||||||
// Binary compatibility kludges, do not use.
|
// Binary compatibility kludges, do not use.
|
||||||
@@ -258,10 +264,10 @@ private:
|
|||||||
CZString(ArrayIndex index);
|
CZString(ArrayIndex index);
|
||||||
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
CZString(CZString const& other);
|
CZString(CZString const& other);
|
||||||
CZString(CZString&& other);
|
CZString(CZString&& other) noexcept;
|
||||||
~CZString();
|
~CZString();
|
||||||
CZString& operator=(const CZString& other);
|
CZString& operator=(const CZString& other);
|
||||||
CZString& operator=(CZString&& other);
|
CZString& operator=(CZString&& other) noexcept;
|
||||||
|
|
||||||
bool operator<(CZString const& other) const;
|
bool operator<(CZString const& other) const;
|
||||||
bool operator==(CZString const& other) const;
|
bool operator==(CZString const& other) const;
|
||||||
@@ -287,11 +293,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
#ifndef JSON_USE_CPPTL_SMALLMAP
|
|
||||||
typedef std::map<CZString, Value> ObjectValues;
|
typedef std::map<CZString, Value> ObjectValues;
|
||||||
#else
|
|
||||||
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
|
|
||||||
#endif // ifndef JSON_USE_CPPTL_SMALLMAP
|
|
||||||
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -340,18 +342,16 @@ public:
|
|||||||
*/
|
*/
|
||||||
Value(const StaticString& value);
|
Value(const StaticString& value);
|
||||||
Value(const String& value);
|
Value(const String& value);
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
Value(const CppTL::ConstString& value);
|
|
||||||
#endif
|
|
||||||
Value(bool value);
|
Value(bool value);
|
||||||
|
Value(std::nullptr_t ptr) = delete;
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
Value(Value&& other);
|
Value(Value&& other) noexcept;
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
/// \note Overwrite existing comments. To preserve comments, use
|
/// \note Overwrite existing comments. To preserve comments, use
|
||||||
/// #swapPayload().
|
/// #swapPayload().
|
||||||
Value& operator=(const Value& other);
|
Value& operator=(const Value& other);
|
||||||
Value& operator=(Value&& other);
|
Value& operator=(Value&& other) noexcept;
|
||||||
|
|
||||||
/// Swap everything.
|
/// Swap everything.
|
||||||
void swap(Value& other);
|
void swap(Value& other);
|
||||||
@@ -375,7 +375,7 @@ public:
|
|||||||
int compare(const Value& other) const;
|
int compare(const Value& other) const;
|
||||||
|
|
||||||
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
const char* asCString() const; ///< Embedded zeroes could cause you trouble!
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
unsigned getCStringLength() const; // Allows you to understand the length of
|
unsigned getCStringLength() const; // Allows you to understand the length of
|
||||||
// the CString
|
// the CString
|
||||||
#endif
|
#endif
|
||||||
@@ -384,9 +384,6 @@ public:
|
|||||||
* \return false if !string. (Seg-fault if str or end are NULL.)
|
* \return false if !string. (Seg-fault if str or end are NULL.)
|
||||||
*/
|
*/
|
||||||
bool getString(char const** begin, char const** end) const;
|
bool getString(char const** begin, char const** end) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
CppTL::ConstString asConstString() const;
|
|
||||||
#endif
|
|
||||||
Int asInt() const;
|
Int asInt() const;
|
||||||
UInt asUInt() const;
|
UInt asUInt() const;
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
@@ -413,8 +410,8 @@ public:
|
|||||||
bool isObject() const;
|
bool isObject() const;
|
||||||
|
|
||||||
/// The `as<T>` and `is<T>` member function templates and specializations.
|
/// The `as<T>` and `is<T>` member function templates and specializations.
|
||||||
template <typename T> T as() const = delete;
|
template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
|
||||||
template <typename T> bool is() const = delete;
|
template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
|
||||||
|
|
||||||
bool isConvertibleTo(ValueType other) const;
|
bool isConvertibleTo(ValueType other) const;
|
||||||
|
|
||||||
@@ -426,7 +423,7 @@ public:
|
|||||||
bool empty() const;
|
bool empty() const;
|
||||||
|
|
||||||
/// Return !isNull()
|
/// Return !isNull()
|
||||||
JSONCPP_OP_EXPLICIT operator bool() const;
|
explicit operator bool() const;
|
||||||
|
|
||||||
/// Remove all object members and array elements.
|
/// Remove all object members and array elements.
|
||||||
/// \pre type() is arrayValue, objectValue, or nullValue
|
/// \pre type() is arrayValue, objectValue, or nullValue
|
||||||
@@ -440,7 +437,7 @@ public:
|
|||||||
/// \post type() is arrayValue
|
/// \post type() is arrayValue
|
||||||
void resize(ArrayIndex newSize);
|
void resize(ArrayIndex newSize);
|
||||||
|
|
||||||
//@{
|
///@{
|
||||||
/// Access an array element (zero based index). If the array contains less
|
/// Access an array element (zero based index). If the array contains less
|
||||||
/// than index element, then null value are inserted in the array so that
|
/// than index element, then null value are inserted in the array so that
|
||||||
/// its size is index+1.
|
/// its size is index+1.
|
||||||
@@ -448,15 +445,15 @@ public:
|
|||||||
/// this from the operator[] which takes a string.)
|
/// this from the operator[] which takes a string.)
|
||||||
Value& operator[](ArrayIndex index);
|
Value& operator[](ArrayIndex index);
|
||||||
Value& operator[](int index);
|
Value& operator[](int index);
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
//@{
|
///@{
|
||||||
/// Access an array element (zero based index).
|
/// Access an array element (zero based index).
|
||||||
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
/// (You may need to say 'value[0u]' to get your compiler to distinguish
|
||||||
/// this from the operator[] which takes a string.)
|
/// this from the operator[] which takes a string.)
|
||||||
const Value& operator[](ArrayIndex index) const;
|
const Value& operator[](ArrayIndex index) const;
|
||||||
const Value& operator[](int index) const;
|
const Value& operator[](int index) const;
|
||||||
//@}
|
///@}
|
||||||
|
|
||||||
/// If the array contains at least index+1 elements, returns the element
|
/// If the array contains at least index+1 elements, returns the element
|
||||||
/// value, otherwise returns defaultValue.
|
/// value, otherwise returns defaultValue.
|
||||||
@@ -468,8 +465,10 @@ public:
|
|||||||
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
/// Equivalent to jsonvalue[jsonvalue.size()] = value;
|
||||||
Value& append(const Value& value);
|
Value& append(const Value& value);
|
||||||
Value& append(Value&& value);
|
Value& append(Value&& value);
|
||||||
|
|
||||||
/// \brief Insert value in array at specific index
|
/// \brief Insert value in array at specific index
|
||||||
bool insert(ArrayIndex index, Value newValue);
|
bool insert(ArrayIndex index, const Value& newValue);
|
||||||
|
bool insert(ArrayIndex index, Value&& newValue);
|
||||||
|
|
||||||
/// Access an object value by name, create a null member if it does not exist.
|
/// Access an object value by name, create a null member if it does not exist.
|
||||||
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
/// \note Because of our implementation, keys are limited to 2^30 -1 chars.
|
||||||
@@ -498,13 +497,6 @@ public:
|
|||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
Value& operator[](const StaticString& key);
|
Value& operator[](const StaticString& key);
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
/// Access an object value by name, create a null member if it does not exist.
|
|
||||||
Value& operator[](const CppTL::ConstString& key);
|
|
||||||
/// Access an object value by name, returns null if there is no member with
|
|
||||||
/// that name.
|
|
||||||
const Value& operator[](const CppTL::ConstString& key) const;
|
|
||||||
#endif
|
|
||||||
/// Return the member named key if it exist, defaultValue otherwise.
|
/// Return the member named key if it exist, defaultValue otherwise.
|
||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
Value get(const char* key, const Value& defaultValue) const;
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
@@ -517,15 +509,13 @@ public:
|
|||||||
/// \note deep copy
|
/// \note deep copy
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
Value get(const String& key, const Value& defaultValue) const;
|
Value get(const String& key, const Value& defaultValue) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
/// Return the member named key if it exist, defaultValue otherwise.
|
|
||||||
/// \note deep copy
|
|
||||||
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
|
|
||||||
#endif
|
|
||||||
/// Most general and efficient version of isMember()const, get()const,
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
/// and operator[]const
|
/// and operator[]const
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
Value const* find(char const* begin, char const* end) const;
|
Value const* find(char const* begin, char const* end) const;
|
||||||
|
/// Most general and efficient version of isMember()const, get()const,
|
||||||
|
/// and operator[]const
|
||||||
|
Value const* find(const String& key) const;
|
||||||
/// Most general and efficient version of object-mutators.
|
/// Most general and efficient version of object-mutators.
|
||||||
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
/// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
|
||||||
@@ -567,10 +557,6 @@ public:
|
|||||||
bool isMember(const String& key) const;
|
bool isMember(const String& key) const;
|
||||||
/// Same as isMember(String const& key)const
|
/// Same as isMember(String const& key)const
|
||||||
bool isMember(const char* begin, const char* end) const;
|
bool isMember(const char* begin, const char* end) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
/// Return true if the object has a member named key.
|
|
||||||
bool isMember(const CppTL::ConstString& key) const;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// \brief Return a list of the member names.
|
/// \brief Return a list of the member names.
|
||||||
///
|
///
|
||||||
@@ -579,11 +565,6 @@ public:
|
|||||||
/// \post if type() was nullValue, it remains nullValue
|
/// \post if type() was nullValue, it remains nullValue
|
||||||
Members getMemberNames() const;
|
Members getMemberNames() const;
|
||||||
|
|
||||||
//# ifdef JSON_USE_CPPTL
|
|
||||||
// EnumMemberNames enumMemberNames() const;
|
|
||||||
// EnumValues enumValues() const;
|
|
||||||
//# endif
|
|
||||||
|
|
||||||
/// \deprecated Always pass len.
|
/// \deprecated Always pass len.
|
||||||
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
|
||||||
void setComment(const char* comment, CommentPlacement placement) {
|
void setComment(const char* comment, CommentPlacement placement) {
|
||||||
@@ -607,6 +588,26 @@ public:
|
|||||||
iterator begin();
|
iterator begin();
|
||||||
iterator end();
|
iterator end();
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the first element in the `Value`.
|
||||||
|
/// Requires that this value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
const Value& front() const;
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the first element in the `Value`.
|
||||||
|
/// Requires that this value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
Value& front();
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the last element in the `Value`.
|
||||||
|
/// Requires that value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
const Value& back() const;
|
||||||
|
|
||||||
|
/// \brief Returns a reference to the last element in the `Value`.
|
||||||
|
/// Requires that this value holds an array or json object, with at least one
|
||||||
|
/// element.
|
||||||
|
Value& back();
|
||||||
|
|
||||||
// Accessors for the [start, limit) range of bytes within the JSON text from
|
// Accessors for the [start, limit) range of bytes within the JSON text from
|
||||||
// which this value was parsed, if any.
|
// which this value was parsed, if any.
|
||||||
void setOffsetStart(ptrdiff_t start);
|
void setOffsetStart(ptrdiff_t start);
|
||||||
@@ -658,9 +659,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
Comments() = default;
|
Comments() = default;
|
||||||
Comments(const Comments& that);
|
Comments(const Comments& that);
|
||||||
Comments(Comments&& that);
|
Comments(Comments&& that) noexcept;
|
||||||
Comments& operator=(const Comments& that);
|
Comments& operator=(const Comments& that);
|
||||||
Comments& operator=(Comments&& that);
|
Comments& operator=(Comments&& that) noexcept;
|
||||||
bool has(CommentPlacement slot) const;
|
bool has(CommentPlacement slot) const;
|
||||||
String get(CommentPlacement slot) const;
|
String get(CommentPlacement slot) const;
|
||||||
void set(CommentPlacement slot, String comment);
|
void set(CommentPlacement slot, String comment);
|
||||||
@@ -706,11 +707,6 @@ template <> inline float Value::as<float>() const { return asFloat(); }
|
|||||||
template <> inline const char* Value::as<const char*>() const {
|
template <> inline const char* Value::as<const char*>() const {
|
||||||
return asCString();
|
return asCString();
|
||||||
}
|
}
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
template <> inline CppTL::ConstString Value::as<CppTL::ConstString>() const {
|
|
||||||
return asConstString();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/** \brief Experimental and untested: represents an element of the "path" to
|
/** \brief Experimental and untested: represents an element of the "path" to
|
||||||
* access a node.
|
* access a node.
|
||||||
@@ -757,8 +753,8 @@ public:
|
|||||||
Value& make(Value& root) const;
|
Value& make(Value& root) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<const PathArgument*> InArgs;
|
using InArgs = std::vector<const PathArgument*>;
|
||||||
typedef std::vector<PathArgument> Args;
|
using Args = std::vector<PathArgument>;
|
||||||
|
|
||||||
void makePath(const String& path, const InArgs& in);
|
void makePath(const String& path, const InArgs& in);
|
||||||
void addPathInArg(const String& path, const InArgs& in,
|
void addPathInArg(const String& path, const InArgs& in,
|
||||||
@@ -773,10 +769,10 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API ValueIteratorBase {
|
class JSON_API ValueIteratorBase {
|
||||||
public:
|
public:
|
||||||
typedef std::bidirectional_iterator_tag iterator_category;
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
typedef unsigned int size_t;
|
using size_t = unsigned int;
|
||||||
typedef int difference_type;
|
using difference_type = int;
|
||||||
typedef ValueIteratorBase SelfType;
|
using SelfType = ValueIteratorBase;
|
||||||
|
|
||||||
bool operator==(const SelfType& other) const { return isEqual(other); }
|
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||||
|
|
||||||
@@ -849,12 +845,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
|
|||||||
friend class Value;
|
friend class Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef const Value value_type;
|
using value_type = const Value;
|
||||||
// typedef unsigned int size_t;
|
// typedef unsigned int size_t;
|
||||||
// typedef int difference_type;
|
// typedef int difference_type;
|
||||||
typedef const Value& reference;
|
using reference = const Value&;
|
||||||
typedef const Value* pointer;
|
using pointer = const Value*;
|
||||||
typedef ValueConstIterator SelfType;
|
using SelfType = ValueConstIterator;
|
||||||
|
|
||||||
ValueConstIterator();
|
ValueConstIterator();
|
||||||
ValueConstIterator(ValueIterator const& other);
|
ValueConstIterator(ValueIterator const& other);
|
||||||
@@ -900,12 +896,12 @@ class JSON_API ValueIterator : public ValueIteratorBase {
|
|||||||
friend class Value;
|
friend class Value;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef Value value_type;
|
using value_type = Value;
|
||||||
typedef unsigned int size_t;
|
using size_t = unsigned int;
|
||||||
typedef int difference_type;
|
using difference_type = int;
|
||||||
typedef Value& reference;
|
using reference = Value&;
|
||||||
typedef Value* pointer;
|
using pointer = Value*;
|
||||||
typedef ValueIterator SelfType;
|
using SelfType = ValueIterator;
|
||||||
|
|
||||||
ValueIterator();
|
ValueIterator();
|
||||||
explicit ValueIterator(const ValueConstIterator& other);
|
explicit ValueIterator(const ValueConstIterator& other);
|
||||||
@@ -946,12 +942,20 @@ public:
|
|||||||
* because the returned references/pointers can be used
|
* because the returned references/pointers can be used
|
||||||
* to change state of the base class.
|
* to change state of the base class.
|
||||||
*/
|
*/
|
||||||
reference operator*() { return deref(); }
|
reference operator*() const { return const_cast<reference>(deref()); }
|
||||||
pointer operator->() { return &deref(); }
|
pointer operator->() const { return const_cast<pointer>(&deref()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void swap(Value& a, Value& b) { a.swap(b); }
|
inline void swap(Value& a, Value& b) { a.swap(b); }
|
||||||
|
|
||||||
|
inline const Value& Value::front() const { return *begin(); }
|
||||||
|
|
||||||
|
inline Value& Value::front() { return *begin(); }
|
||||||
|
|
||||||
|
inline const Value& Value::back() const { return *(--end()); }
|
||||||
|
|
||||||
|
inline Value& Value::back() { return *(--end()); }
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
@@ -960,4 +964,4 @@ inline void swap(Value& a, Value& b) { a.swap(b); }
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_H_INCLUDED
|
#endif // JSON_H_INCLUDED
|
||||||
|
@@ -9,19 +9,18 @@
|
|||||||
// 3. /CMakeLists.txt
|
// 3. /CMakeLists.txt
|
||||||
// IMPORTANT: also update the SOVERSION!!
|
// IMPORTANT: also update the SOVERSION!!
|
||||||
|
|
||||||
#define JSONCPP_VERSION_STRING "1.9.2"
|
#define JSONCPP_VERSION_STRING "1.9.7"
|
||||||
#define JSONCPP_VERSION_MAJOR 1
|
#define JSONCPP_VERSION_MAJOR 1
|
||||||
#define JSONCPP_VERSION_MINOR 9
|
#define JSONCPP_VERSION_MINOR 9
|
||||||
#define JSONCPP_VERSION_PATCH 2
|
#define JSONCPP_VERSION_PATCH 7
|
||||||
#define JSONCPP_VERSION_QUALIFIER
|
#define JSONCPP_VERSION_QUALIFIER
|
||||||
#define JSONCPP_VERSION_HEXA \
|
#define JSONCPP_VERSION_HEXA \
|
||||||
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | \
|
||||||
(JSONCPP_VERSION_PATCH << 8))
|
(JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
#ifdef JSONCPP_USING_SECURE_MEMORY
|
#if !defined(JSONCPP_USE_SECURE_MEMORY)
|
||||||
#undef JSONCPP_USING_SECURE_MEMORY
|
#define JSONCPP_USE_SECURE_MEMORY 0
|
||||||
#endif
|
#endif
|
||||||
#define JSONCPP_USING_SECURE_MEMORY 0
|
|
||||||
// If non-zero, the library zeroes any memory that it has allocated before
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
// it frees its memory.
|
// it frees its memory.
|
||||||
|
|
||||||
|
@@ -20,7 +20,8 @@
|
|||||||
#pragma warning(disable : 4251)
|
#pragma warning(disable : 4251)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
|
||||||
#pragma pack(push, 8)
|
#pragma pack(push)
|
||||||
|
#pragma pack()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
@@ -63,7 +64,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual StreamWriter* newStreamWriter() const = 0;
|
virtual StreamWriter* newStreamWriter() const = 0;
|
||||||
}; // Factory
|
}; // Factory
|
||||||
}; // StreamWriter
|
}; // StreamWriter
|
||||||
|
|
||||||
/** \brief Write into stringstream, then return string, for convenience.
|
/** \brief Write into stringstream, then return string, for convenience.
|
||||||
* A StreamWriter will be created from the factory, used, and then deleted.
|
* A StreamWriter will be created from the factory, used, and then deleted.
|
||||||
@@ -110,6 +111,8 @@ public:
|
|||||||
* - Number of precision digits for formatting of real values.
|
* - Number of precision digits for formatting of real values.
|
||||||
* - "precisionType": "significant"(default) or "decimal"
|
* - "precisionType": "significant"(default) or "decimal"
|
||||||
* - Type of precision for formatting of real values.
|
* - Type of precision for formatting of real values.
|
||||||
|
* - "emitUTF8": false or true
|
||||||
|
* - If true, outputs raw UTF8 strings instead of escaping them.
|
||||||
|
|
||||||
* You can examine 'settings_` yourself
|
* You can examine 'settings_` yourself
|
||||||
* to see the defaults. You can also write and read them just like any
|
* to see the defaults. You can also write and read them just like any
|
||||||
@@ -145,7 +148,7 @@ public:
|
|||||||
/** \brief Abstract class for writers.
|
/** \brief Abstract class for writers.
|
||||||
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||||
*/
|
*/
|
||||||
class JSONCPP_DEPRECATED("Use StreamWriter instead") JSON_API Writer {
|
class JSON_API Writer {
|
||||||
public:
|
public:
|
||||||
virtual ~Writer();
|
virtual ~Writer();
|
||||||
|
|
||||||
@@ -165,8 +168,7 @@ public:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API FastWriter
|
class JSON_API FastWriter : public Writer {
|
||||||
: public Writer {
|
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
~FastWriter() override = default;
|
~FastWriter() override = default;
|
||||||
@@ -215,7 +217,7 @@ private:
|
|||||||
* - otherwise, it the values do not fit on one line, or the array contains
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
* object or non empty array, then print one value per line.
|
* object or non empty array, then print one value per line.
|
||||||
*
|
*
|
||||||
* If the Value have comments then they are outputed according to their
|
* If the Value have comments then they are outputted according to their
|
||||||
*#CommentPlacement.
|
*#CommentPlacement.
|
||||||
*
|
*
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
@@ -225,8 +227,7 @@ private:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
class JSON_API StyledWriter : public Writer {
|
||||||
StyledWriter : public Writer {
|
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
~StyledWriter() override = default;
|
~StyledWriter() override = default;
|
||||||
@@ -252,7 +253,7 @@ private:
|
|||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
static String normalizeEOL(const String& text);
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
typedef std::vector<String> ChildValues;
|
using ChildValues = std::vector<String>;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
String document_;
|
String document_;
|
||||||
@@ -284,7 +285,7 @@ private:
|
|||||||
* - otherwise, it the values do not fit on one line, or the array contains
|
* - otherwise, it the values do not fit on one line, or the array contains
|
||||||
* object or non empty array, then print one value per line.
|
* object or non empty array, then print one value per line.
|
||||||
*
|
*
|
||||||
* If the Value have comments then they are outputed according to their
|
* If the Value have comments then they are outputted according to their
|
||||||
#CommentPlacement.
|
#CommentPlacement.
|
||||||
*
|
*
|
||||||
* \sa Reader, Value, Value::setComment()
|
* \sa Reader, Value, Value::setComment()
|
||||||
@@ -294,8 +295,7 @@ private:
|
|||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
#pragma warning(disable : 4996) // Deriving from deprecated class
|
#pragma warning(disable : 4996) // Deriving from deprecated class
|
||||||
#endif
|
#endif
|
||||||
class JSONCPP_DEPRECATED("Use StreamWriterBuilder instead") JSON_API
|
class JSON_API StyledStreamWriter {
|
||||||
StyledStreamWriter {
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* \param indentation Each level will be indented by this amount extra.
|
* \param indentation Each level will be indented by this amount extra.
|
||||||
@@ -326,7 +326,7 @@ private:
|
|||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
static String normalizeEOL(const String& text);
|
static String normalizeEOL(const String& text);
|
||||||
|
|
||||||
typedef std::vector<String> ChildValues;
|
using ChildValues = std::vector<String>;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
OStream* document_;
|
OStream* document_;
|
||||||
@@ -351,6 +351,7 @@ String JSON_API valueToString(
|
|||||||
PrecisionType precisionType = PrecisionType::significantDigits);
|
PrecisionType precisionType = PrecisionType::significantDigits);
|
||||||
String JSON_API valueToString(bool value);
|
String JSON_API valueToString(bool value);
|
||||||
String JSON_API valueToQuotedString(const char* value);
|
String JSON_API valueToQuotedString(const char* value);
|
||||||
|
String JSON_API valueToQuotedString(const char* value, size_t length);
|
||||||
|
|
||||||
/// \brief Output using the StyledStreamWriter.
|
/// \brief Output using the StyledStreamWriter.
|
||||||
/// \see Json::operator>>()
|
/// \see Json::operator>>()
|
||||||
|
9
jsoncpp-namespaced-targets.cmake
Normal file
9
jsoncpp-namespaced-targets.cmake
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
if (NOT TARGET JsonCpp::JsonCpp)
|
||||||
|
if (TARGET jsoncpp_static)
|
||||||
|
add_library(JsonCpp::JsonCpp INTERFACE IMPORTED)
|
||||||
|
set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_static")
|
||||||
|
elseif (TARGET jsoncpp_lib)
|
||||||
|
add_library(JsonCpp::JsonCpp INTERFACE IMPORTED)
|
||||||
|
set_target_properties(JsonCpp::JsonCpp PROPERTIES INTERFACE_LINK_LIBRARIES "jsoncpp_lib")
|
||||||
|
endif ()
|
||||||
|
endif ()
|
11
jsoncppConfig.cmake.in
Normal file
11
jsoncppConfig.cmake.in
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
cmake_policy(PUSH)
|
||||||
|
cmake_policy(VERSION 3.0...3.26)
|
||||||
|
|
||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-targets.cmake" )
|
||||||
|
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
||||||
|
|
||||||
|
check_required_components(JsonCpp)
|
||||||
|
|
||||||
|
cmake_policy(POP)
|
6
jsoncppConfig.cmake.meson.in
Normal file
6
jsoncppConfig.cmake.meson.in
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
@PACKAGE_INIT@
|
||||||
|
|
||||||
|
@MESON_SHARED_TARGET@
|
||||||
|
@MESON_STATIC_TARGET@
|
||||||
|
|
||||||
|
include ( "${CMAKE_CURRENT_LIST_DIR}/jsoncpp-namespaced-targets.cmake" )
|
87
meson.build
87
meson.build
@@ -9,19 +9,18 @@ project(
|
|||||||
# 2. /include/json/version.h
|
# 2. /include/json/version.h
|
||||||
# 3. /CMakeLists.txt
|
# 3. /CMakeLists.txt
|
||||||
# IMPORTANT: also update the SOVERSION!!
|
# IMPORTANT: also update the SOVERSION!!
|
||||||
version : '1.9.2',
|
version : '1.9.7',
|
||||||
default_options : [
|
default_options : [
|
||||||
'buildtype=release',
|
'buildtype=release',
|
||||||
'cpp_std=c++11',
|
'cpp_std=c++11',
|
||||||
'warning_level=1'],
|
'warning_level=1'],
|
||||||
license : 'Public Domain',
|
license : 'Public Domain',
|
||||||
meson_version : '>= 0.49.0')
|
meson_version : '>= 0.54.0')
|
||||||
|
|
||||||
|
|
||||||
jsoncpp_headers = [
|
jsoncpp_headers = files([
|
||||||
'include/json/allocator.h',
|
'include/json/allocator.h',
|
||||||
'include/json/assertions.h',
|
'include/json/assertions.h',
|
||||||
'include/json/autolink.h',
|
|
||||||
'include/json/config.h',
|
'include/json/config.h',
|
||||||
'include/json/json_features.h',
|
'include/json/json_features.h',
|
||||||
'include/json/forwards.h',
|
'include/json/forwards.h',
|
||||||
@@ -29,7 +28,8 @@ jsoncpp_headers = [
|
|||||||
'include/json/reader.h',
|
'include/json/reader.h',
|
||||||
'include/json/value.h',
|
'include/json/value.h',
|
||||||
'include/json/version.h',
|
'include/json/version.h',
|
||||||
'include/json/writer.h']
|
'include/json/writer.h',
|
||||||
|
])
|
||||||
jsoncpp_include_directories = include_directories('include')
|
jsoncpp_include_directories = include_directories('include')
|
||||||
|
|
||||||
install_headers(
|
install_headers(
|
||||||
@@ -45,13 +45,12 @@ else
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
jsoncpp_lib = library(
|
jsoncpp_lib = library(
|
||||||
'jsoncpp',
|
'jsoncpp', files([
|
||||||
[ jsoncpp_headers,
|
|
||||||
'src/lib_json/json_tool.h',
|
|
||||||
'src/lib_json/json_reader.cpp',
|
'src/lib_json/json_reader.cpp',
|
||||||
'src/lib_json/json_value.cpp',
|
'src/lib_json/json_value.cpp',
|
||||||
'src/lib_json/json_writer.cpp'],
|
'src/lib_json/json_writer.cpp',
|
||||||
soversion : 22,
|
]),
|
||||||
|
soversion : 27,
|
||||||
install : true,
|
install : true,
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
cpp_args: dll_export_flag)
|
cpp_args: dll_export_flag)
|
||||||
@@ -63,22 +62,62 @@ import('pkgconfig').generate(
|
|||||||
filebase : 'jsoncpp',
|
filebase : 'jsoncpp',
|
||||||
description : 'A C++ library for interacting with JSON')
|
description : 'A C++ library for interacting with JSON')
|
||||||
|
|
||||||
|
cmakeconf = configuration_data()
|
||||||
|
cmakeconf.set('MESON_LIB_DIR', get_option('libdir'))
|
||||||
|
cmakeconf.set('MESON_INCLUDE_DIR', get_option('includedir'))
|
||||||
|
|
||||||
|
fs = import('fs')
|
||||||
|
if get_option('default_library') == 'shared'
|
||||||
|
shared_name = fs.name(jsoncpp_lib.full_path())
|
||||||
|
endif
|
||||||
|
if get_option('default_library') == 'static'
|
||||||
|
static_name = fs.name(jsoncpp_lib.full_path())
|
||||||
|
endif
|
||||||
|
if get_option('default_library') == 'both'
|
||||||
|
shared_name = fs.name(jsoncpp_lib.get_shared_lib().full_path())
|
||||||
|
static_name = fs.name(jsoncpp_lib.get_static_lib().full_path())
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('default_library') == 'shared' or get_option('default_library') == 'both'
|
||||||
|
cmakeconf.set('MESON_SHARED_TARGET', '''
|
||||||
|
add_library(jsoncpp_lib IMPORTED SHARED)
|
||||||
|
set_target_properties(jsoncpp_lib PROPERTIES
|
||||||
|
IMPORTED_LOCATION "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('libdir'), shared_name) + '''"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('includedir')) + '")')
|
||||||
|
endif
|
||||||
|
if get_option('default_library') == 'static' or get_option('default_library') == 'both'
|
||||||
|
cmakeconf.set('MESON_STATIC_TARGET', '''
|
||||||
|
add_library(jsoncpp_static IMPORTED STATIC)
|
||||||
|
set_target_properties(jsoncpp_static PROPERTIES
|
||||||
|
IMPORTED_LOCATION "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('libdir'), static_name) + '''"
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "''' + join_paths('${PACKAGE_PREFIX_DIR}', get_option('includedir')) + '")')
|
||||||
|
endif
|
||||||
|
|
||||||
|
import('cmake').configure_package_config_file(
|
||||||
|
name: 'jsoncpp',
|
||||||
|
input: 'jsoncppConfig.cmake.meson.in',
|
||||||
|
configuration: cmakeconf)
|
||||||
|
install_data('jsoncpp-namespaced-targets.cmake', install_dir : join_paths(get_option('libdir'), 'cmake', jsoncpp_lib.name()))
|
||||||
|
|
||||||
# for libraries bundling jsoncpp
|
# for libraries bundling jsoncpp
|
||||||
jsoncpp_dep = declare_dependency(
|
jsoncpp_dep = declare_dependency(
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
link_with : jsoncpp_lib,
|
link_with : jsoncpp_lib,
|
||||||
version : meson.project_version(),
|
version : meson.project_version())
|
||||||
)
|
|
||||||
|
|
||||||
# tests
|
# tests
|
||||||
python = import('python').find_installation()
|
if meson.is_subproject() or not get_option('tests')
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
python = find_program('python3')
|
||||||
|
|
||||||
jsoncpp_test = executable(
|
jsoncpp_test = executable(
|
||||||
'jsoncpp_test',
|
'jsoncpp_test', files([
|
||||||
[ 'src/test_lib_json/jsontest.cpp',
|
'src/test_lib_json/jsontest.cpp',
|
||||||
'src/test_lib_json/jsontest.h',
|
|
||||||
'src/test_lib_json/main.cpp',
|
'src/test_lib_json/main.cpp',
|
||||||
'src/test_lib_json/fuzz.cpp'],
|
'src/test_lib_json/fuzz.cpp',
|
||||||
|
]),
|
||||||
include_directories : jsoncpp_include_directories,
|
include_directories : jsoncpp_include_directories,
|
||||||
link_with : jsoncpp_lib,
|
link_with : jsoncpp_lib,
|
||||||
install : false,
|
install : false,
|
||||||
@@ -101,5 +140,17 @@ test(
|
|||||||
'-B',
|
'-B',
|
||||||
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||||
jsontestrunner,
|
jsontestrunner,
|
||||||
join_paths(meson.current_source_dir(), 'test/data')]
|
join_paths(meson.current_source_dir(), 'test/data')],
|
||||||
|
)
|
||||||
|
test(
|
||||||
|
'jsonchecker_jsontestrunner',
|
||||||
|
python,
|
||||||
|
is_parallel : false,
|
||||||
|
args : [
|
||||||
|
'-B',
|
||||||
|
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||||
|
'--with-json-checker',
|
||||||
|
jsontestrunner,
|
||||||
|
join_paths(meson.current_source_dir(), 'test/data')],
|
||||||
|
workdir : join_paths(meson.current_source_dir(), 'test/data'),
|
||||||
)
|
)
|
||||||
|
5
meson_options.txt
Normal file
5
meson_options.txt
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
option(
|
||||||
|
'tests',
|
||||||
|
type : 'boolean',
|
||||||
|
value : true,
|
||||||
|
description : 'Enable building tests')
|
@@ -1,11 +1,11 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
exec_prefix=@CMAKE_INSTALL_PREFIX@
|
||||||
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
|
libdir=@libdir_for_pc_file@
|
||||||
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
|
includedir=@includedir_for_pc_file@
|
||||||
|
|
||||||
Name: jsoncpp
|
Name: jsoncpp
|
||||||
Description: A C++ library for interacting with JSON
|
Description: A C++ library for interacting with JSON
|
||||||
Version: @JSONCPP_VERSION@
|
Version: @PROJECT_VERSION@
|
||||||
URL: https://github.com/open-source-parsers/jsoncpp
|
URL: https://github.com/open-source-parsers/jsoncpp
|
||||||
Libs: -L${libdir} -ljsoncpp
|
Libs: -L${libdir} -ljsoncpp
|
||||||
Cflags: -I${includedir}
|
Cflags: -I${includedir}
|
||||||
|
1
reformat.sh
Executable file
1
reformat.sh
Executable file
@@ -0,0 +1 @@
|
|||||||
|
find src -name '*.cpp' -or -name '*.h' | xargs clang-format -i
|
@@ -1,26 +1,28 @@
|
|||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
# The new Python3 module is much more robust than the previous PythonInterp
|
# The new Python3 module is much more robust than the previous PythonInterp
|
||||||
find_package (Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
# Set variables for backwards compatibility with cmake < 3.12.0
|
# Set variables for backwards compatibility with cmake < 3.12.0
|
||||||
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
|
||||||
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
|
||||||
else()
|
else()
|
||||||
set(Python_ADDITIONAL_VERSIONS 3.8)
|
set(Python_ADDITIONAL_VERSIONS 3.8)
|
||||||
find_package(PythonInterp 3)
|
find_package(PythonInterp 3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(jsontestrunner_exe
|
add_executable(jsontestrunner_exe
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions( JSON_DLL )
|
add_compile_definitions( JSON_DLL )
|
||||||
else()
|
else()
|
||||||
add_definitions( -DJSON_DLL )
|
add_definitions(-DJSON_DLL)
|
||||||
endif()
|
endif()
|
||||||
|
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
||||||
|
else()
|
||||||
|
target_link_libraries(jsontestrunner_exe jsoncpp_static)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
|
|
||||||
|
|
||||||
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
||||||
|
|
||||||
@@ -32,18 +34,18 @@ if(PYTHONINTERP_FOUND)
|
|||||||
# Run unit tests in post-build
|
# Run unit tests in post-build
|
||||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||||
add_custom_target(jsoncpp_readerwriter_tests
|
add_custom_target(jsoncpp_readerwriter_tests
|
||||||
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
"${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
DEPENDS jsontestrunner_exe jsoncpp_test
|
DEPENDS jsontestrunner_exe jsoncpp_test
|
||||||
)
|
)
|
||||||
add_custom_target(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
|
add_custom_target(jsoncpp_check DEPENDS jsoncpp_readerwriter_tests)
|
||||||
|
|
||||||
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
||||||
add_test(NAME jsoncpp_readerwriter
|
add_test(NAME jsoncpp_readerwriter
|
||||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||||
)
|
)
|
||||||
add_test(NAME jsoncpp_readerwriter_json_checker
|
add_test(NAME jsoncpp_readerwriter_json_checker
|
||||||
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
COMMAND "${PYTHON_EXECUTABLE}" -B "${RUNJSONTESTS_PATH}" --with-json-checker $<TARGET_FILE:jsontestrunner_exe> "${TEST_DIR}/data"
|
||||||
WORKING_DIRECTORY "${TEST_DIR}/data"
|
WORKING_DIRECTORY "${TEST_DIR}/data"
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -57,10 +57,10 @@ static Json::String readInputTestFile(const char* path) {
|
|||||||
if (!file)
|
if (!file)
|
||||||
return "";
|
return "";
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
long const size = ftell(file);
|
auto const size = ftell(file);
|
||||||
size_t const usize = static_cast<unsigned long>(size);
|
auto const usize = static_cast<size_t>(size);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
char* buffer = new char[size + 1];
|
auto buffer = new char[size + 1];
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
Json::String text;
|
Json::String text;
|
||||||
if (fread(buffer, 1, usize, file) == usize)
|
if (fread(buffer, 1, usize, file) == usize)
|
||||||
@@ -111,7 +111,7 @@ static void printValueTree(FILE* fout, Json::Value& value,
|
|||||||
Json::Value::Members members(value.getMemberNames());
|
Json::Value::Members members(value.getMemberNames());
|
||||||
std::sort(members.begin(), members.end());
|
std::sort(members.begin(), members.end());
|
||||||
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||||
for (auto name : members) {
|
for (const auto& name : members) {
|
||||||
printValueTree(fout, value[name], path + suffix + name);
|
printValueTree(fout, value[name], path + suffix + name);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -240,11 +240,14 @@ static int parseCommandLine(int argc, const char* argv[], Options* opts) {
|
|||||||
return printUsage(argv);
|
return printUsage(argv);
|
||||||
}
|
}
|
||||||
int index = 1;
|
int index = 1;
|
||||||
if (Json::String(argv[index]) == "--json-checker") {
|
if (Json::String(argv[index]) == "--parse-only") {
|
||||||
opts->features = Json::Features::strictMode();
|
|
||||||
opts->parseOnly = true;
|
opts->parseOnly = true;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
|
if (Json::String(argv[index]) == "--strict") {
|
||||||
|
opts->features = Json::Features::strictMode();
|
||||||
|
++index;
|
||||||
|
}
|
||||||
if (Json::String(argv[index]) == "--json-config") {
|
if (Json::String(argv[index]) == "--json-config") {
|
||||||
printConfig();
|
printConfig();
|
||||||
return 3;
|
return 3;
|
||||||
@@ -335,6 +338,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
std::cerr << "Unhandled exception:" << std::endl << e.what() << std::endl;
|
std::cerr << "Unhandled exception:" << std::endl << e.what() << std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
|
@@ -1,13 +1,7 @@
|
|||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
|
||||||
#Get compiler version.
|
|
||||||
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
|
||||||
OUTPUT_VARIABLE GNUCXX_VERSION )
|
|
||||||
|
|
||||||
#-Werror=* was introduced -after- GCC 4.1.2
|
#-Werror=* was introduced -after- GCC 4.1.2
|
||||||
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
|
add_compile_options("-Werror=strict-aliasing")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
endif()
|
||||||
endif()
|
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
|
||||||
|
|
||||||
include(CheckIncludeFileCXX)
|
include(CheckIncludeFileCXX)
|
||||||
include(CheckTypeSize)
|
include(CheckTypeSize)
|
||||||
@@ -17,33 +11,23 @@ include(CheckCXXSymbolExists)
|
|||||||
check_include_file_cxx(clocale HAVE_CLOCALE)
|
check_include_file_cxx(clocale HAVE_CLOCALE)
|
||||||
check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
|
check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
|
||||||
|
|
||||||
if(CMAKE_VERSION VERSION_LESS 3.0.0)
|
set(CMAKE_EXTRA_INCLUDE_FILES clocale)
|
||||||
# The "LANGUAGE CXX" parameter is not supported in CMake versions below 3,
|
check_type_size(lconv LCONV_SIZE LANGUAGE CXX)
|
||||||
# so the C compiler and header has to be used.
|
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
||||||
check_include_file(locale.h HAVE_LOCALE_H)
|
check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX)
|
||||||
set(CMAKE_EXTRA_INCLUDE_FILES locale.h)
|
|
||||||
check_type_size("struct lconv" LCONV_SIZE)
|
|
||||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
|
||||||
check_struct_has_member("struct lconv" decimal_point locale.h HAVE_DECIMAL_POINT)
|
|
||||||
else()
|
|
||||||
set(CMAKE_EXTRA_INCLUDE_FILES clocale)
|
|
||||||
check_type_size(lconv LCONV_SIZE LANGUAGE CXX)
|
|
||||||
unset(CMAKE_EXTRA_INCLUDE_FILES)
|
|
||||||
check_struct_has_member(lconv decimal_point clocale HAVE_DECIMAL_POINT LANGUAGE CXX)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALECONV))
|
||||||
message(WARNING "Locale functionality is not supported")
|
message(WARNING "Locale functionality is not supported")
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
|
add_compile_definitions(JSONCPP_NO_LOCALE_SUPPORT)
|
||||||
else()
|
else()
|
||||||
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
|
add_definitions(-DJSONCPP_NO_LOCALE_SUPPORT)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set( JSONCPP_INCLUDE_DIR ../../include )
|
set(JSONCPP_INCLUDE_DIR ../../include)
|
||||||
|
|
||||||
set( PUBLIC_HEADERS
|
set(PUBLIC_HEADERS
|
||||||
${JSONCPP_INCLUDE_DIR}/json/config.h
|
${JSONCPP_INCLUDE_DIR}/json/config.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
${JSONCPP_INCLUDE_DIR}/json/forwards.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/json_features.h
|
${JSONCPP_INCLUDE_DIR}/json/json_features.h
|
||||||
@@ -52,49 +36,29 @@ set( PUBLIC_HEADERS
|
|||||||
${JSONCPP_INCLUDE_DIR}/json/version.h
|
${JSONCPP_INCLUDE_DIR}/json/version.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
${JSONCPP_INCLUDE_DIR}/json/writer.h
|
||||||
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
${JSONCPP_INCLUDE_DIR}/json/assertions.h
|
||||||
)
|
)
|
||||||
|
|
||||||
source_group( "Public API" FILES ${PUBLIC_HEADERS} )
|
source_group("Public API" FILES ${PUBLIC_HEADERS})
|
||||||
|
|
||||||
set(jsoncpp_sources
|
set(JSONCPP_SOURCES
|
||||||
json_tool.h
|
json_tool.h
|
||||||
json_reader.cpp
|
json_reader.cpp
|
||||||
json_valueiterator.inl
|
json_valueiterator.inl
|
||||||
json_value.cpp
|
json_value.cpp
|
||||||
json_writer.cpp)
|
json_writer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
# Install instructions for this target
|
# Install instructions for this target
|
||||||
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
if(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
set(INSTALL_EXPORT EXPORT jsoncpp)
|
set(INSTALL_EXPORT EXPORT jsoncpp)
|
||||||
else(JSONCPP_WITH_CMAKE_PACKAGE)
|
else()
|
||||||
set(INSTALL_EXPORT)
|
set(INSTALL_EXPORT)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
|
||||||
add_compile_definitions( JSON_DLL_BUILD )
|
|
||||||
else()
|
|
||||||
add_definitions( -DJSON_DLL_BUILD )
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
|
|
||||||
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
|
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
|
|
||||||
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
|
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
|
|
||||||
|
|
||||||
# Set library's runtime search path on OSX
|
|
||||||
if(APPLE)
|
|
||||||
set_target_properties( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Specify compiler features required when compiling a given target.
|
# Specify compiler features required when compiling a given target.
|
||||||
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
|
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
|
||||||
# for complete list of features available
|
# for complete list of features available
|
||||||
target_compile_features(jsoncpp_lib PUBLIC
|
list(APPEND REQUIRED_FEATURES
|
||||||
cxx_std_11 # Compiler mode is aware of C++ 11.
|
cxx_std_11 # Compiler mode is aware of C++ 11.
|
||||||
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
|
||||||
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
|
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
|
||||||
@@ -141,14 +105,101 @@ target_compile_features(jsoncpp_lib PUBLIC
|
|||||||
cxx_variadic_templates # Variadic templates, as defined in N2242.
|
cxx_variadic_templates # Variadic templates, as defined in N2242.
|
||||||
)
|
)
|
||||||
|
|
||||||
install( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
|
||||||
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
|
||||||
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
|
||||||
|
|
||||||
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
if(BUILD_SHARED_LIBS)
|
||||||
target_include_directories( jsoncpp_lib PUBLIC
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
add_compile_definitions(JSON_DLL_BUILD)
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
else()
|
||||||
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>)
|
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 ${BUILD_SHARED_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
|
||||||
|
target_include_directories(${SHARED_LIB} PUBLIC
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND CMAKE_TARGETS ${SHARED_LIB})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(BUILD_STATIC_LIBS)
|
||||||
|
set(STATIC_LIB ${PROJECT_NAME}_static)
|
||||||
|
add_library(${STATIC_LIB} STATIC ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
|
||||||
|
|
||||||
|
# avoid name clashes on windows as the shared import lib is also named jsoncpp.lib
|
||||||
|
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
|
||||||
|
if (MSVC OR ("${CMAKE_C_SIMULATE_ID}" STREQUAL "MSVC"))
|
||||||
|
set(STATIC_SUFFIX "_static")
|
||||||
|
else()
|
||||||
|
set(STATIC_SUFFIX "")
|
||||||
|
endif()
|
||||||
|
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})
|
||||||
|
|
||||||
|
target_include_directories(${STATIC_LIB} PUBLIC
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
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 ${BUILD_SHARED_LIBS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# 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})
|
||||||
|
|
||||||
|
target_include_directories(${OBJECT_LIB} PUBLIC
|
||||||
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||||
|
)
|
||||||
|
|
||||||
|
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}
|
||||||
|
)
|
||||||
|
|
||||||
|
@@ -10,7 +10,9 @@
|
|||||||
#include <json/reader.h>
|
#include <json/reader.h>
|
||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cmath>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
@@ -21,13 +23,6 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
|
|
||||||
#if !defined(sscanf)
|
|
||||||
#define sscanf std::sscanf
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif //__cplusplus
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
||||||
@@ -51,11 +46,7 @@ static size_t const stackLimit_g =
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
|
||||||
using CharReaderPtr = std::unique_ptr<CharReader>;
|
using CharReaderPtr = std::unique_ptr<CharReader>;
|
||||||
#else
|
|
||||||
typedef std::auto_ptr<CharReader> CharReaderPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Implementation of class Features
|
// Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
@@ -77,10 +68,7 @@ Features Features::strictMode() {
|
|||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
|
||||||
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
|
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
|
||||||
for (; begin < end; ++begin)
|
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
|
||||||
if (*begin == '\n' || *begin == '\r')
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class Reader
|
// Class Reader
|
||||||
@@ -106,8 +94,7 @@ bool Reader::parse(std::istream& is, Value& root, bool collectComments) {
|
|||||||
|
|
||||||
// Since String is reference-counted, this at least does not
|
// Since String is reference-counted, this at least does not
|
||||||
// create an extra copy.
|
// create an extra copy.
|
||||||
String doc;
|
String doc(std::istreambuf_iterator<char>(is), {});
|
||||||
std::getline(is, doc, static_cast<char> EOF);
|
|
||||||
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
|
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +118,7 @@ bool Reader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
|
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
if (collectComments_ && !commentsBefore_.empty())
|
if (collectComments_ && !commentsBefore_.empty())
|
||||||
root.setComment(commentsBefore_, commentAfter);
|
root.setComment(commentsBefore_, commentAfter);
|
||||||
if (features_.strictRoot_) {
|
if (features_.strictRoot_) {
|
||||||
@@ -159,7 +146,7 @@ bool Reader::readValue() {
|
|||||||
throwRuntimeError("Exceeded stackLimit in readValue().");
|
throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
@@ -227,14 +214,14 @@ bool Reader::readValue() {
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::skipCommentTokens(Token& token) {
|
bool Reader::readTokenSkippingComments(Token& token) {
|
||||||
|
bool success = readToken(token);
|
||||||
if (features_.allowComments_) {
|
if (features_.allowComments_) {
|
||||||
do {
|
while (success && token.type_ == tokenComment) {
|
||||||
readToken(token);
|
success = readToken(token);
|
||||||
} while (token.type_ == tokenComment);
|
}
|
||||||
} else {
|
|
||||||
readToken(token);
|
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readToken(Token& token) {
|
bool Reader::readToken(Token& token) {
|
||||||
@@ -448,12 +435,7 @@ bool Reader::readObject(Token& token) {
|
|||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
while (readToken(tokenName)) {
|
while (readTokenSkippingComments(tokenName)) {
|
||||||
bool initialTokenOk = true;
|
|
||||||
while (tokenName.type_ == tokenComment && initialTokenOk)
|
|
||||||
initialTokenOk = readToken(tokenName);
|
|
||||||
if (!initialTokenOk)
|
|
||||||
break;
|
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
||||||
return true;
|
return true;
|
||||||
name.clear();
|
name.clear();
|
||||||
@@ -464,7 +446,7 @@ bool Reader::readObject(Token& token) {
|
|||||||
Value numberName;
|
Value numberName;
|
||||||
if (!decodeNumber(tokenName, numberName))
|
if (!decodeNumber(tokenName, numberName))
|
||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
name = String(numberName.asCString());
|
name = numberName.asString();
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -482,15 +464,11 @@ bool Reader::readObject(Token& token) {
|
|||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
|
|
||||||
Token comma;
|
Token comma;
|
||||||
if (!readToken(comma) ||
|
if (!readTokenSkippingComments(comma) ||
|
||||||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
|
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
|
||||||
comma.type_ != tokenComment)) {
|
|
||||||
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
||||||
comma, tokenObjectEnd);
|
comma, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
bool finalizeTokenOk = true;
|
|
||||||
while (comma.type_ == tokenComment && finalizeTokenOk)
|
|
||||||
finalizeTokenOk = readToken(comma);
|
|
||||||
if (comma.type_ == tokenObjectEnd)
|
if (comma.type_ == tokenObjectEnd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -520,10 +498,7 @@ bool Reader::readArray(Token& token) {
|
|||||||
|
|
||||||
Token currentToken;
|
Token currentToken;
|
||||||
// Accept Comment after last item in the array.
|
// Accept Comment after last item in the array.
|
||||||
ok = readToken(currentToken);
|
ok = readTokenSkippingComments(currentToken);
|
||||||
while (currentToken.type_ == tokenComment && ok) {
|
|
||||||
ok = readToken(currentToken);
|
|
||||||
}
|
|
||||||
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
||||||
currentToken.type_ != tokenArrayEnd);
|
currentToken.type_ != tokenArrayEnd);
|
||||||
if (!ok || badTokenType) {
|
if (!ok || badTokenType) {
|
||||||
@@ -601,11 +576,16 @@ bool Reader::decodeDouble(Token& token) {
|
|||||||
|
|
||||||
bool Reader::decodeDouble(Token& token, Value& decoded) {
|
bool Reader::decodeDouble(Token& token, Value& decoded) {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
String buffer(token.start_, token.end_);
|
IStringStream is(String(token.start_, token.end_));
|
||||||
IStringStream is(buffer);
|
if (!(is >> value)) {
|
||||||
if (!(is >> value))
|
if (value == std::numeric_limits<double>::max())
|
||||||
return addError(
|
value = std::numeric_limits<double>::infinity();
|
||||||
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
else if (value == std::numeric_limits<double>::lowest())
|
||||||
|
value = -std::numeric_limits<double>::infinity();
|
||||||
|
else if (!std::isinf(value))
|
||||||
|
return addError(
|
||||||
|
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
||||||
|
}
|
||||||
decoded = value;
|
decoded = value;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -629,7 +609,7 @@ bool Reader::decodeString(Token& token, String& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '"')
|
if (c == '"')
|
||||||
break;
|
break;
|
||||||
else if (c == '\\') {
|
if (c == '\\') {
|
||||||
if (current == end)
|
if (current == end)
|
||||||
return addError("Empty escape sequence in string", token, current);
|
return addError("Empty escape sequence in string", token, current);
|
||||||
Char escape = *current++;
|
Char escape = *current++;
|
||||||
@@ -769,7 +749,7 @@ void Reader::getLocationLineAndColumn(Location location, int& line,
|
|||||||
while (current < location && current != end_) {
|
while (current < location && current != end_) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
if (*current == '\n')
|
if (current != end_ && *current == '\n')
|
||||||
++current;
|
++current;
|
||||||
lastLineStart = current;
|
lastLineStart = current;
|
||||||
++line;
|
++line;
|
||||||
@@ -863,6 +843,7 @@ class OurFeatures {
|
|||||||
public:
|
public:
|
||||||
static OurFeatures all();
|
static OurFeatures all();
|
||||||
bool allowComments_;
|
bool allowComments_;
|
||||||
|
bool allowTrailingCommas_;
|
||||||
bool strictRoot_;
|
bool strictRoot_;
|
||||||
bool allowDroppedNullPlaceholders_;
|
bool allowDroppedNullPlaceholders_;
|
||||||
bool allowNumericKeys_;
|
bool allowNumericKeys_;
|
||||||
@@ -870,6 +851,7 @@ public:
|
|||||||
bool failIfExtra_;
|
bool failIfExtra_;
|
||||||
bool rejectDupKeys_;
|
bool rejectDupKeys_;
|
||||||
bool allowSpecialFloats_;
|
bool allowSpecialFloats_;
|
||||||
|
bool skipBom_;
|
||||||
size_t stackLimit_;
|
size_t stackLimit_;
|
||||||
}; // OurFeatures
|
}; // OurFeatures
|
||||||
|
|
||||||
@@ -884,17 +866,12 @@ class OurReader {
|
|||||||
public:
|
public:
|
||||||
using Char = char;
|
using Char = char;
|
||||||
using Location = const Char*;
|
using Location = const Char*;
|
||||||
struct StructuredError {
|
|
||||||
ptrdiff_t offset_start;
|
|
||||||
ptrdiff_t offset_limit;
|
|
||||||
String message;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit OurReader(OurFeatures const& features);
|
explicit OurReader(OurFeatures const& features);
|
||||||
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
bool parse(const char* beginDoc, const char* endDoc, Value& root,
|
||||||
bool collectComments = true);
|
bool collectComments = true);
|
||||||
String getFormattedErrorMessages() const;
|
String getFormattedErrorMessages() const;
|
||||||
std::vector<StructuredError> getStructuredErrors() const;
|
std::vector<CharReader::StructuredError> getStructuredErrors() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OurReader(OurReader const&); // no impl
|
OurReader(OurReader const&); // no impl
|
||||||
@@ -937,7 +914,9 @@ private:
|
|||||||
using Errors = std::deque<ErrorInfo>;
|
using Errors = std::deque<ErrorInfo>;
|
||||||
|
|
||||||
bool readToken(Token& token);
|
bool readToken(Token& token);
|
||||||
|
bool readTokenSkippingComments(Token& token);
|
||||||
void skipSpaces();
|
void skipSpaces();
|
||||||
|
void skipBom(bool skipBom);
|
||||||
bool match(const Char* pattern, int patternLength);
|
bool match(const Char* pattern, int patternLength);
|
||||||
bool readComment();
|
bool readComment();
|
||||||
bool readCStyleComment(bool* containsNewLineResult);
|
bool readCStyleComment(bool* containsNewLineResult);
|
||||||
@@ -969,7 +948,6 @@ private:
|
|||||||
int& column) const;
|
int& column) const;
|
||||||
String getLocationLineAndColumn(Location location) const;
|
String getLocationLineAndColumn(Location location) const;
|
||||||
void addComment(Location begin, Location end, CommentPlacement placement);
|
void addComment(Location begin, Location end, CommentPlacement placement);
|
||||||
void skipCommentTokens(Token& token);
|
|
||||||
|
|
||||||
static String normalizeEOL(Location begin, Location end);
|
static String normalizeEOL(Location begin, Location end);
|
||||||
static bool containsNewLine(Location begin, Location end);
|
static bool containsNewLine(Location begin, Location end);
|
||||||
@@ -995,10 +973,7 @@ private:
|
|||||||
|
|
||||||
bool OurReader::containsNewLine(OurReader::Location begin,
|
bool OurReader::containsNewLine(OurReader::Location begin,
|
||||||
OurReader::Location end) {
|
OurReader::Location end) {
|
||||||
for (; begin < end; ++begin)
|
return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
|
||||||
if (*begin == '\n' || *begin == '\r')
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
|
OurReader::OurReader(OurFeatures const& features) : features_(features) {}
|
||||||
@@ -1021,10 +996,12 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
|
|||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
|
// skip byte order mark if it exists at the beginning of the UTF-8 text.
|
||||||
|
skipBom(features_.skipBom_);
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
|
if (features_.failIfExtra_ && (token.type_ != tokenEndOfStream)) {
|
||||||
addError("Extra non-whitespace after JSON value.", token);
|
addError("Extra non-whitespace after JSON value.", token);
|
||||||
return false;
|
return false;
|
||||||
@@ -1052,7 +1029,7 @@ bool OurReader::readValue() {
|
|||||||
if (nodes_.size() > features_.stackLimit_)
|
if (nodes_.size() > features_.stackLimit_)
|
||||||
throwRuntimeError("Exceeded stackLimit in readValue().");
|
throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
readTokenSkippingComments(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
@@ -1139,14 +1116,14 @@ bool OurReader::readValue() {
|
|||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OurReader::skipCommentTokens(Token& token) {
|
bool OurReader::readTokenSkippingComments(Token& token) {
|
||||||
|
bool success = readToken(token);
|
||||||
if (features_.allowComments_) {
|
if (features_.allowComments_) {
|
||||||
do {
|
while (success && token.type_ == tokenComment) {
|
||||||
readToken(token);
|
success = readToken(token);
|
||||||
} while (token.type_ == tokenComment);
|
}
|
||||||
} else {
|
|
||||||
readToken(token);
|
|
||||||
}
|
}
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::readToken(Token& token) {
|
bool OurReader::readToken(Token& token) {
|
||||||
@@ -1175,8 +1152,11 @@ bool OurReader::readToken(Token& token) {
|
|||||||
if (features_.allowSingleQuotes_) {
|
if (features_.allowSingleQuotes_) {
|
||||||
token.type_ = tokenString;
|
token.type_ = tokenString;
|
||||||
ok = readStringSingleQuote();
|
ok = readStringSingleQuote();
|
||||||
break;
|
} else {
|
||||||
} // else fall through
|
// If we don't allow single quotes, this is a failure case.
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
token.type_ = tokenComment;
|
token.type_ = tokenComment;
|
||||||
ok = readComment();
|
ok = readComment();
|
||||||
@@ -1267,6 +1247,16 @@ void OurReader::skipSpaces() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OurReader::skipBom(bool skipBom) {
|
||||||
|
// The default behavior is to skip BOM.
|
||||||
|
if (skipBom) {
|
||||||
|
if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
|
||||||
|
begin_ += 3;
|
||||||
|
current_ = begin_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool OurReader::match(const Char* pattern, int patternLength) {
|
bool OurReader::match(const Char* pattern, int patternLength) {
|
||||||
if (end_ - current_ < patternLength)
|
if (end_ - current_ < patternLength)
|
||||||
return false;
|
return false;
|
||||||
@@ -1349,11 +1339,10 @@ bool OurReader::readCStyleComment(bool* containsNewLineResult) {
|
|||||||
|
|
||||||
while ((current_ + 1) < end_) {
|
while ((current_ + 1) < end_) {
|
||||||
Char c = getNextChar();
|
Char c = getNextChar();
|
||||||
if (c == '*' && *current_ == '/') {
|
if (c == '*' && *current_ == '/')
|
||||||
break;
|
break;
|
||||||
} else if (c == '\n') {
|
if (c == '\n')
|
||||||
*containsNewLineResult = true;
|
*containsNewLineResult = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return getNextChar() == '/';
|
return getNextChar() == '/';
|
||||||
@@ -1431,13 +1420,10 @@ bool OurReader::readObject(Token& token) {
|
|||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
while (readToken(tokenName)) {
|
while (readTokenSkippingComments(tokenName)) {
|
||||||
bool initialTokenOk = true;
|
if (tokenName.type_ == tokenObjectEnd &&
|
||||||
while (tokenName.type_ == tokenComment && initialTokenOk)
|
(name.empty() ||
|
||||||
initialTokenOk = readToken(tokenName);
|
features_.allowTrailingCommas_)) // empty object or trailing comma
|
||||||
if (!initialTokenOk)
|
|
||||||
break;
|
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
|
||||||
return true;
|
return true;
|
||||||
name.clear();
|
name.clear();
|
||||||
if (tokenName.type_ == tokenString) {
|
if (tokenName.type_ == tokenString) {
|
||||||
@@ -1471,15 +1457,11 @@ bool OurReader::readObject(Token& token) {
|
|||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
|
|
||||||
Token comma;
|
Token comma;
|
||||||
if (!readToken(comma) ||
|
if (!readTokenSkippingComments(comma) ||
|
||||||
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
|
(comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator)) {
|
||||||
comma.type_ != tokenComment)) {
|
|
||||||
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
return addErrorAndRecover("Missing ',' or '}' in object declaration",
|
||||||
comma, tokenObjectEnd);
|
comma, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
bool finalizeTokenOk = true;
|
|
||||||
while (comma.type_ == tokenComment && finalizeTokenOk)
|
|
||||||
finalizeTokenOk = readToken(comma);
|
|
||||||
if (comma.type_ == tokenObjectEnd)
|
if (comma.type_ == tokenObjectEnd)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1491,15 +1473,19 @@ bool OurReader::readArray(Token& token) {
|
|||||||
Value init(arrayValue);
|
Value init(arrayValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(token.start_ - begin_);
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
skipSpaces();
|
|
||||||
if (current_ != end_ && *current_ == ']') // empty array
|
|
||||||
{
|
|
||||||
Token endArray;
|
|
||||||
readToken(endArray);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
skipSpaces();
|
||||||
|
if (current_ != end_ && *current_ == ']' &&
|
||||||
|
(index == 0 ||
|
||||||
|
(features_.allowTrailingCommas_ &&
|
||||||
|
!features_.allowDroppedNullPlaceholders_))) // empty array or trailing
|
||||||
|
// comma
|
||||||
|
{
|
||||||
|
Token endArray;
|
||||||
|
readToken(endArray);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
Value& value = currentValue()[index++];
|
Value& value = currentValue()[index++];
|
||||||
nodes_.push(&value);
|
nodes_.push(&value);
|
||||||
bool ok = readValue();
|
bool ok = readValue();
|
||||||
@@ -1509,10 +1495,7 @@ bool OurReader::readArray(Token& token) {
|
|||||||
|
|
||||||
Token currentToken;
|
Token currentToken;
|
||||||
// Accept Comment after last item in the array.
|
// Accept Comment after last item in the array.
|
||||||
ok = readToken(currentToken);
|
ok = readTokenSkippingComments(currentToken);
|
||||||
while (currentToken.type_ == tokenComment && ok) {
|
|
||||||
ok = readToken(currentToken);
|
|
||||||
}
|
|
||||||
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
bool badTokenType = (currentToken.type_ != tokenArraySeparator &&
|
||||||
currentToken.type_ != tokenArrayEnd);
|
currentToken.type_ != tokenArrayEnd);
|
||||||
if (!ok || badTokenType) {
|
if (!ok || badTokenType) {
|
||||||
@@ -1571,9 +1554,9 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
// then take the inverse. This assumes that minLargestInt is only a single
|
// then take the inverse. This assumes that minLargestInt is only a single
|
||||||
// power of 10 different in magnitude, which we check above. For the last
|
// power of 10 different in magnitude, which we check above. For the last
|
||||||
// digit, we take the modulus before negating for the same reason.
|
// digit, we take the modulus before negating for the same reason.
|
||||||
static constexpr Value::LargestUInt negative_threshold =
|
static constexpr auto negative_threshold =
|
||||||
Value::LargestUInt(-(Value::minLargestInt / 10));
|
Value::LargestUInt(-(Value::minLargestInt / 10));
|
||||||
static constexpr Value::UInt negative_last_digit =
|
static constexpr auto negative_last_digit =
|
||||||
Value::UInt(-(Value::minLargestInt % 10));
|
Value::UInt(-(Value::minLargestInt % 10));
|
||||||
|
|
||||||
const Value::LargestUInt threshold =
|
const Value::LargestUInt threshold =
|
||||||
@@ -1587,10 +1570,10 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
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) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, meaing value == threshold,
|
// a) we've only just touched the limit, meaning value == threshold,
|
||||||
// b) this is the last digit, or
|
// b) this is the last digit, or
|
||||||
// c) it's small enough to fit in that rounding delta, we're okay.
|
// c) it's small enough to fit in that rounding delta, we're okay.
|
||||||
// Otherwise treat this number as a double to avoid overflow.
|
// Otherwise treat this number as a double to avoid overflow.
|
||||||
@@ -1604,7 +1587,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
|
|
||||||
if (isNegative) {
|
if (isNegative) {
|
||||||
// We use the same magnitude assumption here, just in case.
|
// 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;
|
decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
|
||||||
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
|
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
|
||||||
decoded = Value::LargestInt(value);
|
decoded = Value::LargestInt(value);
|
||||||
@@ -1627,11 +1610,15 @@ bool OurReader::decodeDouble(Token& token) {
|
|||||||
|
|
||||||
bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
||||||
double value = 0;
|
double value = 0;
|
||||||
const String buffer(token.start_, token.end_);
|
IStringStream is(String(token.start_, token.end_));
|
||||||
IStringStream is(buffer);
|
|
||||||
if (!(is >> value)) {
|
if (!(is >> value)) {
|
||||||
return addError(
|
if (value == std::numeric_limits<double>::max())
|
||||||
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
value = std::numeric_limits<double>::infinity();
|
||||||
|
else if (value == std::numeric_limits<double>::lowest())
|
||||||
|
value = -std::numeric_limits<double>::infinity();
|
||||||
|
else if (!std::isinf(value))
|
||||||
|
return addError(
|
||||||
|
"'" + String(token.start_, token.end_) + "' is not a number.", token);
|
||||||
}
|
}
|
||||||
decoded = value;
|
decoded = value;
|
||||||
return true;
|
return true;
|
||||||
@@ -1654,9 +1641,9 @@ bool OurReader::decodeString(Token& token, String& decoded) {
|
|||||||
Location end = token.end_ - 1; // do not include '"'
|
Location end = token.end_ - 1; // do not include '"'
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '"') {
|
if (c == '"')
|
||||||
break;
|
break;
|
||||||
} else if (c == '\\') {
|
if (c == '\\') {
|
||||||
if (current == end)
|
if (current == end)
|
||||||
return addError("Empty escape sequence in string", token, current);
|
return addError("Empty escape sequence in string", token, current);
|
||||||
Char escape = *current++;
|
Char escape = *current++;
|
||||||
@@ -1796,7 +1783,7 @@ void OurReader::getLocationLineAndColumn(Location location, int& line,
|
|||||||
while (current < location && current != end_) {
|
while (current < location && current != end_) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c == '\r') {
|
if (c == '\r') {
|
||||||
if (*current == '\n')
|
if (current != end_ && *current == '\n')
|
||||||
++current;
|
++current;
|
||||||
lastLineStart = current;
|
lastLineStart = current;
|
||||||
++line;
|
++line;
|
||||||
@@ -1831,10 +1818,11 @@ String OurReader::getFormattedErrorMessages() const {
|
|||||||
return formattedMessage;
|
return formattedMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
std::vector<CharReader::StructuredError>
|
||||||
std::vector<OurReader::StructuredError> allErrors;
|
OurReader::getStructuredErrors() const {
|
||||||
|
std::vector<CharReader::StructuredError> allErrors;
|
||||||
for (const auto& error : errors_) {
|
for (const auto& error : errors_) {
|
||||||
OurReader::StructuredError structured;
|
CharReader::StructuredError structured;
|
||||||
structured.offset_start = error.token_.start_ - begin_;
|
structured.offset_start = error.token_.start_ - begin_;
|
||||||
structured.offset_limit = error.token_.end_ - begin_;
|
structured.offset_limit = error.token_.end_ - begin_;
|
||||||
structured.message = error.message_;
|
structured.message = error.message_;
|
||||||
@@ -1844,20 +1832,36 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class OurCharReader : public CharReader {
|
class OurCharReader : public CharReader {
|
||||||
bool const collectComments_;
|
|
||||||
OurReader reader_;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OurCharReader(bool collectComments, OurFeatures const& features)
|
OurCharReader(bool collectComments, OurFeatures const& features)
|
||||||
: collectComments_(collectComments), reader_(features) {}
|
: CharReader(
|
||||||
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
std::unique_ptr<OurImpl>(new OurImpl(collectComments, features))) {}
|
||||||
String* errs) override {
|
|
||||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
protected:
|
||||||
if (errs) {
|
class OurImpl : public Impl {
|
||||||
*errs = reader_.getFormattedErrorMessages();
|
public:
|
||||||
|
OurImpl(bool collectComments, OurFeatures const& features)
|
||||||
|
: collectComments_(collectComments), reader_(features) {}
|
||||||
|
|
||||||
|
bool parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) override {
|
||||||
|
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||||
|
if (errs) {
|
||||||
|
*errs = reader_.getFormattedErrorMessages();
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
}
|
}
|
||||||
return ok;
|
|
||||||
}
|
std::vector<CharReader::StructuredError>
|
||||||
|
getStructuredErrors() const override {
|
||||||
|
return reader_.getStructuredErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool const collectComments_;
|
||||||
|
OurReader reader_;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
CharReaderBuilder::CharReaderBuilder() { setDefaults(&settings_); }
|
||||||
@@ -1866,6 +1870,7 @@ CharReader* CharReaderBuilder::newCharReader() const {
|
|||||||
bool collectComments = settings_["collectComments"].asBool();
|
bool collectComments = settings_["collectComments"].asBool();
|
||||||
OurFeatures features = OurFeatures::all();
|
OurFeatures features = OurFeatures::all();
|
||||||
features.allowComments_ = settings_["allowComments"].asBool();
|
features.allowComments_ = settings_["allowComments"].asBool();
|
||||||
|
features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
|
||||||
features.strictRoot_ = settings_["strictRoot"].asBool();
|
features.strictRoot_ = settings_["strictRoot"].asBool();
|
||||||
features.allowDroppedNullPlaceholders_ =
|
features.allowDroppedNullPlaceholders_ =
|
||||||
settings_["allowDroppedNullPlaceholders"].asBool();
|
settings_["allowDroppedNullPlaceholders"].asBool();
|
||||||
@@ -1878,38 +1883,37 @@ CharReader* CharReaderBuilder::newCharReader() const {
|
|||||||
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
features.failIfExtra_ = settings_["failIfExtra"].asBool();
|
||||||
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
|
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
|
||||||
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
|
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
|
||||||
|
features.skipBom_ = settings_["skipBom"].asBool();
|
||||||
return new OurCharReader(collectComments, features);
|
return new OurCharReader(collectComments, features);
|
||||||
}
|
}
|
||||||
static void getValidReaderKeys(std::set<String>* valid_keys) {
|
|
||||||
valid_keys->clear();
|
|
||||||
valid_keys->insert("collectComments");
|
|
||||||
valid_keys->insert("allowComments");
|
|
||||||
valid_keys->insert("strictRoot");
|
|
||||||
valid_keys->insert("allowDroppedNullPlaceholders");
|
|
||||||
valid_keys->insert("allowNumericKeys");
|
|
||||||
valid_keys->insert("allowSingleQuotes");
|
|
||||||
valid_keys->insert("stackLimit");
|
|
||||||
valid_keys->insert("failIfExtra");
|
|
||||||
valid_keys->insert("rejectDupKeys");
|
|
||||||
valid_keys->insert("allowSpecialFloats");
|
|
||||||
}
|
|
||||||
bool CharReaderBuilder::validate(Json::Value* invalid) const {
|
bool CharReaderBuilder::validate(Json::Value* invalid) const {
|
||||||
Json::Value my_invalid;
|
static const auto& valid_keys = *new std::set<String>{
|
||||||
if (!invalid)
|
"collectComments",
|
||||||
invalid = &my_invalid; // so we do not need to test for NULL
|
"allowComments",
|
||||||
Json::Value& inv = *invalid;
|
"allowTrailingCommas",
|
||||||
std::set<String> valid_keys;
|
"strictRoot",
|
||||||
getValidReaderKeys(&valid_keys);
|
"allowDroppedNullPlaceholders",
|
||||||
Value::Members keys = settings_.getMemberNames();
|
"allowNumericKeys",
|
||||||
size_t n = keys.size();
|
"allowSingleQuotes",
|
||||||
for (size_t i = 0; i < n; ++i) {
|
"stackLimit",
|
||||||
String const& key = keys[i];
|
"failIfExtra",
|
||||||
if (valid_keys.find(key) == valid_keys.end()) {
|
"rejectDupKeys",
|
||||||
inv[key] = settings_[key];
|
"allowSpecialFloats",
|
||||||
}
|
"skipBom",
|
||||||
|
};
|
||||||
|
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
|
||||||
|
auto key = si.name();
|
||||||
|
if (valid_keys.count(key))
|
||||||
|
continue;
|
||||||
|
if (invalid)
|
||||||
|
(*invalid)[key] = *si;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return inv.empty();
|
return invalid ? invalid->empty() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& CharReaderBuilder::operator[](const String& key) {
|
Value& CharReaderBuilder::operator[](const String& key) {
|
||||||
return settings_[key];
|
return settings_[key];
|
||||||
}
|
}
|
||||||
@@ -1917,6 +1921,7 @@ Value& CharReaderBuilder::operator[](const String& key) {
|
|||||||
void CharReaderBuilder::strictMode(Json::Value* settings) {
|
void CharReaderBuilder::strictMode(Json::Value* settings) {
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
(*settings)["allowComments"] = false;
|
(*settings)["allowComments"] = false;
|
||||||
|
(*settings)["allowTrailingCommas"] = false;
|
||||||
(*settings)["strictRoot"] = true;
|
(*settings)["strictRoot"] = true;
|
||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
@@ -1925,6 +1930,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
|
|||||||
(*settings)["failIfExtra"] = true;
|
(*settings)["failIfExtra"] = true;
|
||||||
(*settings)["rejectDupKeys"] = true;
|
(*settings)["rejectDupKeys"] = true;
|
||||||
(*settings)["allowSpecialFloats"] = false;
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = true;
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
}
|
}
|
||||||
// static
|
// static
|
||||||
@@ -1932,6 +1938,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
|
|||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
(*settings)["collectComments"] = true;
|
(*settings)["collectComments"] = true;
|
||||||
(*settings)["allowComments"] = true;
|
(*settings)["allowComments"] = true;
|
||||||
|
(*settings)["allowTrailingCommas"] = true;
|
||||||
(*settings)["strictRoot"] = false;
|
(*settings)["strictRoot"] = false;
|
||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
@@ -1940,8 +1947,35 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
|
|||||||
(*settings)["failIfExtra"] = false;
|
(*settings)["failIfExtra"] = false;
|
||||||
(*settings)["rejectDupKeys"] = false;
|
(*settings)["rejectDupKeys"] = false;
|
||||||
(*settings)["allowSpecialFloats"] = false;
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = true;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
// static
|
||||||
|
void CharReaderBuilder::ecma404Mode(Json::Value* settings) {
|
||||||
|
//! [CharReaderBuilderECMA404Mode]
|
||||||
|
(*settings)["allowComments"] = false;
|
||||||
|
(*settings)["allowTrailingCommas"] = false;
|
||||||
|
(*settings)["strictRoot"] = false;
|
||||||
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
|
(*settings)["allowNumericKeys"] = false;
|
||||||
|
(*settings)["allowSingleQuotes"] = false;
|
||||||
|
(*settings)["stackLimit"] = 1000;
|
||||||
|
(*settings)["failIfExtra"] = true;
|
||||||
|
(*settings)["rejectDupKeys"] = false;
|
||||||
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
|
(*settings)["skipBom"] = false;
|
||||||
|
//! [CharReaderBuilderECMA404Mode]
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<CharReader::StructuredError>
|
||||||
|
CharReader::getStructuredErrors() const {
|
||||||
|
return _impl->getStructuredErrors();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharReader::parse(char const* beginDoc, char const* endDoc, Value* root,
|
||||||
|
String* errs) {
|
||||||
|
return _impl->parse(beginDoc, endDoc, root, errs);
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
// global functions
|
// global functions
|
||||||
@@ -1950,7 +1984,7 @@ bool parseFromStream(CharReader::Factory const& fact, IStream& sin, Value* root,
|
|||||||
String* errs) {
|
String* errs) {
|
||||||
OStringStream ssin;
|
OStringStream ssin;
|
||||||
ssin << sin.rdbuf();
|
ssin << sin.rdbuf();
|
||||||
String doc = ssin.str();
|
String doc = std::move(ssin).str();
|
||||||
char const* begin = doc.data();
|
char const* begin = doc.data();
|
||||||
char const* end = begin + doc.size();
|
char const* end = begin + doc.size();
|
||||||
// Note that we do not actually need a null-terminator.
|
// Note that we do not actually need a null-terminator.
|
||||||
|
@@ -71,7 +71,7 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Defines a char buffer for use with uintToString().
|
// Defines a char buffer for use with uintToString().
|
||||||
typedef char UIntToStringBuffer[uintToStringBufferSize];
|
using UIntToStringBuffer = char[uintToStringBufferSize];
|
||||||
|
|
||||||
/** Converts an unsigned integer to string.
|
/** Converts an unsigned integer to string.
|
||||||
* @param value Unsigned integer to convert to string
|
* @param value Unsigned integer to convert to string
|
||||||
@@ -116,14 +116,18 @@ template <typename Iter> void fixNumericLocaleInput(Iter begin, Iter end) {
|
|||||||
* Return iterator that would be the new end of the range [begin,end), if we
|
* Return iterator that would be the new end of the range [begin,end), if we
|
||||||
* were to delete zeros in the end of string, but not the last zero before '.'.
|
* were to delete zeros in the end of string, but not the last zero before '.'.
|
||||||
*/
|
*/
|
||||||
template <typename Iter> Iter fixZerosInTheEnd(Iter begin, Iter end) {
|
template <typename Iter>
|
||||||
|
Iter fixZerosInTheEnd(Iter begin, Iter end, unsigned int precision) {
|
||||||
for (; begin != end; --end) {
|
for (; begin != end; --end) {
|
||||||
if (*(end - 1) != '0') {
|
if (*(end - 1) != '0') {
|
||||||
return end;
|
return end;
|
||||||
}
|
}
|
||||||
// Don't delete the last zero before the decimal point.
|
// Don't delete the last zero before the decimal point.
|
||||||
if (begin != (end - 1) && *(end - 2) == '.') {
|
if (begin != (end - 1) && begin != (end - 2) && *(end - 2) == '.') {
|
||||||
return end;
|
if (precision) {
|
||||||
|
return end;
|
||||||
|
}
|
||||||
|
return end - 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return end;
|
return end;
|
||||||
|
@@ -8,16 +8,14 @@
|
|||||||
#include <json/value.h>
|
#include <json/value.h>
|
||||||
#include <json/writer.h>
|
#include <json/writer.h>
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstddef>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
#include <cpptl/conststring.h>
|
|
||||||
#endif
|
|
||||||
#include <algorithm> // min()
|
|
||||||
#include <cstddef> // size_t
|
|
||||||
|
|
||||||
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
// Provide implementation equivalent of std::snprintf for older _MSC compilers
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1900
|
#if defined(_MSC_VER) && _MSC_VER < 1900
|
||||||
@@ -89,7 +87,8 @@ template <typename T, typename U>
|
|||||||
static inline bool InRange(double d, T min, U max) {
|
static inline bool InRange(double d, T min, U max) {
|
||||||
// The casts can lose precision, but we are looking only for
|
// The casts can lose precision, but we are looking only for
|
||||||
// an approximate range. Might fail on edge cases though. ~cdunn
|
// an approximate range. Might fail on edge cases though. ~cdunn
|
||||||
return d >= static_cast<double>(min) && d <= static_cast<double>(max);
|
return d >= static_cast<double>(min) && d <= static_cast<double>(max) &&
|
||||||
|
!(static_cast<U>(d) == min && d != static_cast<double>(min));
|
||||||
}
|
}
|
||||||
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
static inline double integerToDouble(Json::UInt64 value) {
|
static inline double integerToDouble(Json::UInt64 value) {
|
||||||
@@ -103,7 +102,8 @@ template <typename T> static inline double integerToDouble(T value) {
|
|||||||
|
|
||||||
template <typename T, typename U>
|
template <typename T, typename U>
|
||||||
static inline bool InRange(double d, T min, U max) {
|
static inline bool InRange(double d, T min, U max) {
|
||||||
return d >= integerToDouble(min) && d <= integerToDouble(max);
|
return d >= integerToDouble(min) && d <= integerToDouble(max) &&
|
||||||
|
!(static_cast<U>(d) == min && d != integerToDouble(min));
|
||||||
}
|
}
|
||||||
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
|
|||||||
if (length >= static_cast<size_t>(Value::maxInt))
|
if (length >= static_cast<size_t>(Value::maxInt))
|
||||||
length = Value::maxInt - 1;
|
length = Value::maxInt - 1;
|
||||||
|
|
||||||
char* newString = static_cast<char*>(malloc(length + 1));
|
auto newString = static_cast<char*>(malloc(length + 1));
|
||||||
if (newString == nullptr) {
|
if (newString == nullptr) {
|
||||||
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
@@ -140,8 +140,8 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
|
|||||||
sizeof(unsigned) - 1U,
|
sizeof(unsigned) - 1U,
|
||||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"length too big for prefixing");
|
"length too big for prefixing");
|
||||||
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
|
size_t actualLength = sizeof(length) + length + 1;
|
||||||
char* newString = static_cast<char*>(malloc(actualLength));
|
auto newString = static_cast<char*>(malloc(actualLength));
|
||||||
if (newString == nullptr) {
|
if (newString == nullptr) {
|
||||||
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
@@ -165,7 +165,7 @@ inline static void decodePrefixedString(bool isPrefixed, char const* prefixed,
|
|||||||
/** Free the string duplicated by
|
/** Free the string duplicated by
|
||||||
* duplicateStringValue()/duplicateAndPrefixStringValue().
|
* duplicateStringValue()/duplicateAndPrefixStringValue().
|
||||||
*/
|
*/
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
static inline void releasePrefixedStringValue(char* value) {
|
static inline void releasePrefixedStringValue(char* value) {
|
||||||
unsigned length = 0;
|
unsigned length = 0;
|
||||||
char const* valueDecoded;
|
char const* valueDecoded;
|
||||||
@@ -180,10 +180,10 @@ static inline void releaseStringValue(char* value, unsigned length) {
|
|||||||
memset(value, 0, size);
|
memset(value, 0, size);
|
||||||
free(value);
|
free(value);
|
||||||
}
|
}
|
||||||
#else // !JSONCPP_USING_SECURE_MEMORY
|
#else // !JSONCPP_USE_SECURE_MEMORY
|
||||||
static inline void releasePrefixedStringValue(char* value) { free(value); }
|
static inline void releasePrefixedStringValue(char* value) { free(value); }
|
||||||
static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
static inline void releaseStringValue(char* value, unsigned) { free(value); }
|
||||||
#endif // JSONCPP_USING_SECURE_MEMORY
|
#endif // JSONCPP_USE_SECURE_MEMORY
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
@@ -203,8 +203,8 @@ namespace Json {
|
|||||||
|
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
Exception::Exception(String msg) : msg_(std::move(msg)) {}
|
Exception::Exception(String msg) : msg_(std::move(msg)) {}
|
||||||
Exception::~Exception() JSONCPP_NOEXCEPT = default;
|
Exception::~Exception() noexcept = default;
|
||||||
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); }
|
char const* Exception::what() const noexcept { return msg_.c_str(); }
|
||||||
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
|
||||||
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
LogicError::LogicError(String const& msg) : Exception(msg) {}
|
||||||
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
||||||
@@ -214,8 +214,14 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
|||||||
throw LogicError(msg);
|
throw LogicError(msg);
|
||||||
}
|
}
|
||||||
#else // !JSON_USE_EXCEPTION
|
#else // !JSON_USE_EXCEPTION
|
||||||
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { abort(); }
|
JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
|
||||||
JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); }
|
std::cerr << msg << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
JSONCPP_NORETURN void throwLogicError(String const& msg) {
|
||||||
|
std::cerr << msg << std::endl;
|
||||||
|
abort();
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -255,7 +261,7 @@ Value::CZString::CZString(const CZString& other) {
|
|||||||
storage_.length_ = other.storage_.length_;
|
storage_.length_ = other.storage_.length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::CZString::CZString(CZString&& other)
|
Value::CZString::CZString(CZString&& other) noexcept
|
||||||
: cstr_(other.cstr_), index_(other.index_) {
|
: cstr_(other.cstr_), index_(other.index_) {
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = nullptr;
|
||||||
}
|
}
|
||||||
@@ -281,7 +287,7 @@ Value::CZString& Value::CZString::operator=(const CZString& other) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::CZString& Value::CZString::operator=(CZString&& other) {
|
Value::CZString& Value::CZString::operator=(CZString&& other) noexcept {
|
||||||
cstr_ = other.cstr_;
|
cstr_ = other.cstr_;
|
||||||
index_ = other.index_;
|
index_ = other.index_;
|
||||||
other.cstr_ = nullptr;
|
other.cstr_ = nullptr;
|
||||||
@@ -419,14 +425,6 @@ Value::Value(const StaticString& value) {
|
|||||||
value_.string_ = const_cast<char*>(value.c_str());
|
value_.string_ = const_cast<char*>(value.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
Value::Value(const CppTL::ConstString& value) {
|
|
||||||
initBasic(stringValue, true);
|
|
||||||
value_.string_ = duplicateAndPrefixStringValue(
|
|
||||||
value, static_cast<unsigned>(value.length()));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Value::Value(bool value) {
|
Value::Value(bool value) {
|
||||||
initBasic(booleanValue);
|
initBasic(booleanValue);
|
||||||
value_.bool_ = value;
|
value_.bool_ = value;
|
||||||
@@ -437,7 +435,7 @@ Value::Value(const Value& other) {
|
|||||||
dupMeta(other);
|
dupMeta(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Value(Value&& other) {
|
Value::Value(Value&& other) noexcept {
|
||||||
initBasic(nullValue);
|
initBasic(nullValue);
|
||||||
swap(other);
|
swap(other);
|
||||||
}
|
}
|
||||||
@@ -452,7 +450,7 @@ Value& Value::operator=(const Value& other) {
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& Value::operator=(Value&& other) {
|
Value& Value::operator=(Value&& other) noexcept {
|
||||||
other.swap(*this);
|
other.swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -529,9 +527,10 @@ bool Value::operator<(const Value& other) const {
|
|||||||
}
|
}
|
||||||
case arrayValue:
|
case arrayValue:
|
||||||
case objectValue: {
|
case objectValue: {
|
||||||
int delta = int(value_.map_->size() - other.value_.map_->size());
|
auto thisSize = value_.map_->size();
|
||||||
if (delta)
|
auto otherSize = other.value_.map_->size();
|
||||||
return delta < 0;
|
if (thisSize != otherSize)
|
||||||
|
return thisSize < otherSize;
|
||||||
return (*value_.map_) < (*other.value_.map_);
|
return (*value_.map_) < (*other.value_.map_);
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
@@ -602,7 +601,7 @@ const char* Value::asCString() const {
|
|||||||
return this_str;
|
return this_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
unsigned Value::getCStringLength() const {
|
unsigned Value::getCStringLength() const {
|
||||||
JSON_ASSERT_MESSAGE(type() == stringValue,
|
JSON_ASSERT_MESSAGE(type() == stringValue,
|
||||||
"in Json::Value::asCString(): requires stringValue");
|
"in Json::Value::asCString(): requires stringValue");
|
||||||
@@ -654,15 +653,6 @@ String Value::asString() const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
CppTL::ConstString Value::asConstString() const {
|
|
||||||
unsigned len;
|
|
||||||
char const* str;
|
|
||||||
decodePrefixedString(isAllocated(), value_.string_, &len, &str);
|
|
||||||
return CppTL::ConstString(str, len);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Value::Int Value::asInt() const {
|
Value::Int Value::asInt() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
case intValue:
|
case intValue:
|
||||||
@@ -694,7 +684,7 @@ Value::UInt Value::asUInt() const {
|
|||||||
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
|
JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
|
||||||
return UInt(value_.uint_);
|
return UInt(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt),
|
||||||
"double out of UInt range");
|
"double out of UInt range");
|
||||||
return UInt(value_.real_);
|
return UInt(value_.real_);
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@@ -717,6 +707,11 @@ Value::Int64 Value::asInt64() const {
|
|||||||
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
|
||||||
return Int64(value_.uint_);
|
return Int64(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
|
// If the double value is in proximity to minInt64, it will be rounded to
|
||||||
|
// minInt64. The correct value in this scenario is indeterminable
|
||||||
|
JSON_ASSERT_MESSAGE(
|
||||||
|
value_.real_ != minInt64,
|
||||||
|
"Double value is minInt64, precise value cannot be determined");
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
|
||||||
"double out of Int64 range");
|
"double out of Int64 range");
|
||||||
return Int64(value_.real_);
|
return Int64(value_.real_);
|
||||||
@@ -738,7 +733,7 @@ Value::UInt64 Value::asUInt64() const {
|
|||||||
case uintValue:
|
case uintValue:
|
||||||
return UInt64(value_.uint_);
|
return UInt64(value_.uint_);
|
||||||
case realValue:
|
case realValue:
|
||||||
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
|
JSON_ASSERT_MESSAGE(InRange(value_.real_, 0u, maxUInt64),
|
||||||
"double out of UInt64 range");
|
"double out of UInt64 range");
|
||||||
return UInt64(value_.real_);
|
return UInt64(value_.real_);
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@@ -849,7 +844,7 @@ bool Value::isConvertibleTo(ValueType other) const {
|
|||||||
type() == booleanValue || type() == nullValue;
|
type() == booleanValue || type() == nullValue;
|
||||||
case uintValue:
|
case uintValue:
|
||||||
return isUInt() ||
|
return isUInt() ||
|
||||||
(type() == realValue && InRange(value_.real_, 0, maxUInt)) ||
|
(type() == realValue && InRange(value_.real_, 0u, maxUInt)) ||
|
||||||
type() == booleanValue || type() == nullValue;
|
type() == booleanValue || type() == nullValue;
|
||||||
case realValue:
|
case realValue:
|
||||||
return isNumeric() || type() == booleanValue || type() == nullValue;
|
return isNumeric() || type() == booleanValue || type() == nullValue;
|
||||||
@@ -894,8 +889,7 @@ ArrayIndex Value::size() const {
|
|||||||
bool Value::empty() const {
|
bool Value::empty() const {
|
||||||
if (isNull() || isArray() || isObject())
|
if (isNull() || isArray() || isObject())
|
||||||
return size() == 0U;
|
return size() == 0U;
|
||||||
else
|
return false;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::operator bool() const { return !isNull(); }
|
Value::operator bool() const { return !isNull(); }
|
||||||
@@ -925,7 +919,8 @@ void Value::resize(ArrayIndex newSize) {
|
|||||||
if (newSize == 0)
|
if (newSize == 0)
|
||||||
clear();
|
clear();
|
||||||
else if (newSize > oldSize)
|
else if (newSize > oldSize)
|
||||||
this->operator[](newSize - 1);
|
for (ArrayIndex i = oldSize; i < newSize; ++i)
|
||||||
|
(*this)[i];
|
||||||
else {
|
else {
|
||||||
for (ArrayIndex index = newSize; index < oldSize; ++index) {
|
for (ArrayIndex index = newSize; index < oldSize; ++index) {
|
||||||
value_.map_->erase(index);
|
value_.map_->erase(index);
|
||||||
@@ -1104,6 +1099,9 @@ Value const* Value::find(char const* begin, char const* end) const {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
return &(*it).second;
|
return &(*it).second;
|
||||||
}
|
}
|
||||||
|
Value const* Value::find(const String& key) const {
|
||||||
|
return find(key.data(), key.data() + key.length());
|
||||||
|
}
|
||||||
Value* Value::demand(char const* begin, char const* end) {
|
Value* Value::demand(char const* begin, char const* end) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == objectValue,
|
||||||
"in Json::Value::demand(begin, end): requires "
|
"in Json::Value::demand(begin, end): requires "
|
||||||
@@ -1117,7 +1115,7 @@ const Value& Value::operator[](const char* key) const {
|
|||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
Value const& Value::operator[](const String& key) const {
|
Value const& Value::operator[](const String& key) const {
|
||||||
Value const* found = find(key.data(), key.data() + key.length());
|
Value const* found = find(key);
|
||||||
if (!found)
|
if (!found)
|
||||||
return nullSingleton();
|
return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
@@ -1135,18 +1133,6 @@ Value& Value::operator[](const StaticString& key) {
|
|||||||
return resolveReference(key.c_str());
|
return resolveReference(key.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
Value& Value::operator[](const CppTL::ConstString& key) {
|
|
||||||
return resolveReference(key.c_str(), key.end_c_str());
|
|
||||||
}
|
|
||||||
Value const& Value::operator[](CppTL::ConstString const& key) const {
|
|
||||||
Value const* found = find(key.c_str(), key.end_c_str());
|
|
||||||
if (!found)
|
|
||||||
return nullSingleton();
|
|
||||||
return *found;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Value& Value::append(const Value& value) { return append(Value(value)); }
|
Value& Value::append(const Value& value) { return append(Value(value)); }
|
||||||
|
|
||||||
Value& Value::append(Value&& value) {
|
Value& Value::append(Value&& value) {
|
||||||
@@ -1158,19 +1144,22 @@ Value& Value::append(Value&& value) {
|
|||||||
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
return this->value_.map_->emplace(size(), std::move(value)).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::insert(ArrayIndex index, Value newValue) {
|
bool Value::insert(ArrayIndex index, const Value& newValue) {
|
||||||
|
return insert(index, Value(newValue));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Value::insert(ArrayIndex index, Value&& newValue) {
|
||||||
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
|
||||||
"in Json::Value::insert: requires arrayValue");
|
"in Json::Value::insert: requires arrayValue");
|
||||||
ArrayIndex length = size();
|
ArrayIndex length = size();
|
||||||
if (index > length) {
|
if (index > length) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
|
||||||
for (ArrayIndex i = length; i > index; i--) {
|
|
||||||
(*this)[i] = std::move((*this)[i - 1]);
|
|
||||||
}
|
|
||||||
(*this)[index] = std::move(newValue);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
for (ArrayIndex i = length; i > index; i--) {
|
||||||
|
(*this)[i] = std::move((*this)[i - 1]);
|
||||||
|
}
|
||||||
|
(*this)[index] = std::move(newValue);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value Value::get(char const* begin, char const* end,
|
Value Value::get(char const* begin, char const* end,
|
||||||
@@ -1226,7 +1215,7 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (removed)
|
if (removed)
|
||||||
*removed = it->second;
|
*removed = std::move(it->second);
|
||||||
ArrayIndex oldSize = size();
|
ArrayIndex oldSize = size();
|
||||||
// shift left all items left, into the place of the "removed"
|
// shift left all items left, into the place of the "removed"
|
||||||
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
|
for (ArrayIndex i = index; i < (oldSize - 1); ++i) {
|
||||||
@@ -1240,13 +1229,6 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
Value Value::get(const CppTL::ConstString& key,
|
|
||||||
const Value& defaultValue) const {
|
|
||||||
return get(key.c_str(), key.end_c_str(), defaultValue);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
bool Value::isMember(char const* begin, char const* end) const {
|
bool Value::isMember(char const* begin, char const* end) const {
|
||||||
Value const* value = find(begin, end);
|
Value const* value = find(begin, end);
|
||||||
return nullptr != value;
|
return nullptr != value;
|
||||||
@@ -1258,12 +1240,6 @@ bool Value::isMember(String const& key) const {
|
|||||||
return isMember(key.data(), key.data() + key.length());
|
return isMember(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef JSON_USE_CPPTL
|
|
||||||
bool Value::isMember(const CppTL::ConstString& key) const {
|
|
||||||
return isMember(key.c_str(), key.end_c_str());
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Value::Members Value::getMemberNames() const {
|
Value::Members Value::getMemberNames() const {
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
type() == nullValue || type() == objectValue,
|
type() == nullValue || type() == objectValue,
|
||||||
@@ -1279,31 +1255,6 @@ Value::Members Value::getMemberNames() const {
|
|||||||
}
|
}
|
||||||
return members;
|
return members;
|
||||||
}
|
}
|
||||||
//
|
|
||||||
//# ifdef JSON_USE_CPPTL
|
|
||||||
// EnumMemberNames
|
|
||||||
// Value::enumMemberNames() const
|
|
||||||
//{
|
|
||||||
// if ( type() == objectValue )
|
|
||||||
// {
|
|
||||||
// return CppTL::Enum::any( CppTL::Enum::transform(
|
|
||||||
// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
|
|
||||||
// MemberNamesTransform() ) );
|
|
||||||
// }
|
|
||||||
// return EnumMemberNames();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// EnumValues
|
|
||||||
// Value::enumValues() const
|
|
||||||
//{
|
|
||||||
// if ( type() == objectValue || type() == arrayValue )
|
|
||||||
// return CppTL::Enum::anyValues( *(value_.map_),
|
|
||||||
// CppTL::Type<const Value &>() );
|
|
||||||
// return EnumValues();
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//# endif
|
|
||||||
|
|
||||||
static bool IsIntegral(double d) {
|
static bool IsIntegral(double d) {
|
||||||
double integral_part;
|
double integral_part;
|
||||||
@@ -1367,8 +1318,12 @@ bool Value::isInt64() const {
|
|||||||
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
// Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
|
||||||
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
// double, so double(maxInt64) will be rounded up to 2^63. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double
|
||||||
value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
|
// values in its proximity are also rounded to -2^63, we require the value
|
||||||
|
// to be strictly greater than the limit to avoid returning 'true' for
|
||||||
|
// values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) && value_.real_ < double(maxInt64) &&
|
||||||
|
IsIntegral(value_.real_);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1406,7 +1361,11 @@ bool Value::isIntegral() const {
|
|||||||
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
// Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
|
||||||
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
// double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
|
||||||
// require the value to be strictly less than the limit.
|
// require the value to be strictly less than the limit.
|
||||||
return value_.real_ >= double(minInt64) &&
|
// minInt64 is -2^63 which can be represented as a double, but since double
|
||||||
|
// values in its proximity are also rounded to -2^63, we require the value
|
||||||
|
// to be strictly greater than the limit to avoid returning 'true' for
|
||||||
|
// values that are not in the range
|
||||||
|
return value_.real_ > double(minInt64) &&
|
||||||
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
||||||
#else
|
#else
|
||||||
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
return value_.real_ >= minInt && value_.real_ <= maxUInt &&
|
||||||
@@ -1433,14 +1392,15 @@ bool Value::isObject() const { return type() == objectValue; }
|
|||||||
Value::Comments::Comments(const Comments& that)
|
Value::Comments::Comments(const Comments& that)
|
||||||
: ptr_{cloneUnique(that.ptr_)} {}
|
: ptr_{cloneUnique(that.ptr_)} {}
|
||||||
|
|
||||||
Value::Comments::Comments(Comments&& that) : ptr_{std::move(that.ptr_)} {}
|
Value::Comments::Comments(Comments&& that) noexcept
|
||||||
|
: ptr_{std::move(that.ptr_)} {}
|
||||||
|
|
||||||
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
Value::Comments& Value::Comments::operator=(const Comments& that) {
|
||||||
ptr_ = cloneUnique(that.ptr_);
|
ptr_ = cloneUnique(that.ptr_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Comments& Value::Comments::operator=(Comments&& that) {
|
Value::Comments& Value::Comments::operator=(Comments&& that) noexcept {
|
||||||
ptr_ = std::move(that.ptr_);
|
ptr_ = std::move(that.ptr_);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -1456,13 +1416,11 @@ String Value::Comments::get(CommentPlacement slot) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Value::Comments::set(CommentPlacement slot, String comment) {
|
void Value::Comments::set(CommentPlacement slot, String comment) {
|
||||||
if (!ptr_) {
|
if (slot >= CommentPlacement::numberOfCommentPlacement)
|
||||||
|
return;
|
||||||
|
if (!ptr_)
|
||||||
ptr_ = std::unique_ptr<Array>(new Array());
|
ptr_ = std::unique_ptr<Array>(new Array());
|
||||||
}
|
(*ptr_)[slot] = std::move(comment);
|
||||||
// check comments array boundry.
|
|
||||||
if (slot < CommentPlacement::numberOfCommentPlacement) {
|
|
||||||
(*ptr_)[slot] = std::move(comment);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::setComment(String comment, CommentPlacement placement) {
|
void Value::setComment(String comment, CommentPlacement placement) {
|
||||||
@@ -1470,9 +1428,8 @@ void Value::setComment(String comment, CommentPlacement placement) {
|
|||||||
// Always discard trailing newline, to aid indentation.
|
// Always discard trailing newline, to aid indentation.
|
||||||
comment.pop_back();
|
comment.pop_back();
|
||||||
}
|
}
|
||||||
JSON_ASSERT(!comment.empty());
|
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
comment[0] == '\0' || comment[0] == '/',
|
comment.empty() || comment[0] == '/',
|
||||||
"in Json::Value::setComment(): Comments must start with /");
|
"in Json::Value::setComment(): Comments must start with /");
|
||||||
comments_.set(placement, std::move(comment));
|
comments_.set(placement, std::move(comment));
|
||||||
}
|
}
|
||||||
|
@@ -30,9 +30,6 @@ void ValueIteratorBase::decrement() { --current_; }
|
|||||||
|
|
||||||
ValueIteratorBase::difference_type
|
ValueIteratorBase::difference_type
|
||||||
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
ValueIteratorBase::computeDistance(const SelfType& other) const {
|
||||||
#ifdef JSON_USE_CPPTL_SMALLMAP
|
|
||||||
return other.current_ - current_;
|
|
||||||
#else
|
|
||||||
// Iterator for null value are initialized using the default
|
// Iterator for null value are initialized using the default
|
||||||
// constructor, which initialize current_ to the default
|
// constructor, which initialize current_ to the default
|
||||||
// std::map::iterator. As begin() and end() are two instance
|
// std::map::iterator. As begin() and end() are two instance
|
||||||
@@ -53,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
|
|||||||
++myDistance;
|
++myDistance;
|
||||||
}
|
}
|
||||||
return myDistance;
|
return myDistance;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
bool ValueIteratorBase::isEqual(const SelfType& other) const {
|
||||||
|
@@ -7,7 +7,11 @@
|
|||||||
#include "json_tool.h"
|
#include "json_tool.h"
|
||||||
#include <json/writer.h>
|
#include <json/writer.h>
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -15,67 +19,6 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#if !defined(isnan)
|
|
||||||
#define isnan std::isnan
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#define isfinite std::isfinite
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#else
|
|
||||||
#include <cmath>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
|
||||||
#if !defined(isnan)
|
|
||||||
#include <float.h>
|
|
||||||
#define isnan _isnan
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#include <float.h>
|
|
||||||
#define isfinite _finite
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
|
|
||||||
#define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
|
|
||||||
#endif //_CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES
|
|
||||||
|
|
||||||
#endif //_MSC_VER
|
|
||||||
|
|
||||||
#if defined(__sun) && defined(__SVR4) // Solaris
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#include <ieeefp.h>
|
|
||||||
#define isfinite finite
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__hpux)
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#if defined(__ia64) && !defined(finite)
|
|
||||||
#define isfinite(x) \
|
|
||||||
((sizeof(x) == sizeof(float) ? _Isfinitef(x) : _IsFinite(x)))
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(isnan)
|
|
||||||
// IEEE standard states that NaN values will not compare to themselves
|
|
||||||
#define isnan(x) (x != x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(__APPLE__)
|
|
||||||
#if !defined(isfinite)
|
|
||||||
#define isfinite finite
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
// Disable warning about strdup being deprecated.
|
// Disable warning about strdup being deprecated.
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
@@ -83,11 +26,7 @@
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
|
||||||
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
using StreamWriterPtr = std::unique_ptr<StreamWriter>;
|
||||||
#else
|
|
||||||
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String valueToString(LargestInt value) {
|
String valueToString(LargestInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
@@ -127,11 +66,12 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
// Print into the buffer. We need not request the alternative representation
|
// Print into the buffer. We need not request the alternative representation
|
||||||
// that always has a decimal point because JSON doesn't distinguish the
|
// that always has a decimal point because JSON doesn't distinguish the
|
||||||
// concepts of reals and integers.
|
// concepts of reals and integers.
|
||||||
if (!isfinite(value)) {
|
if (!std::isfinite(value)) {
|
||||||
static const char* const reps[2][3] = {{"NaN", "-Infinity", "Infinity"},
|
if (std::isnan(value))
|
||||||
{"null", "-1e+9999", "1e+9999"}};
|
return useSpecialFloats ? "NaN" : "null";
|
||||||
return reps[useSpecialFloats ? 0 : 1]
|
if (value < 0)
|
||||||
[isnan(value) ? 0 : (value < 0) ? 1 : 2];
|
return useSpecialFloats ? "-Infinity" : "-1e+9999";
|
||||||
|
return useSpecialFloats ? "Infinity" : "1e+9999";
|
||||||
}
|
}
|
||||||
|
|
||||||
String buffer(size_t(36), '\0');
|
String buffer(size_t(36), '\0');
|
||||||
@@ -152,16 +92,18 @@ String valueToString(double value, bool useSpecialFloats,
|
|||||||
|
|
||||||
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
buffer.erase(fixNumericLocale(buffer.begin(), buffer.end()), buffer.end());
|
||||||
|
|
||||||
// strip the zero padding from the right
|
|
||||||
if (precisionType == PrecisionType::decimalPlaces) {
|
|
||||||
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end()), buffer.end());
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to ensure we preserve the fact that this was given to us as a double on
|
// try to ensure we preserve the fact that this was given to us as a double on
|
||||||
// input
|
// input
|
||||||
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
|
if (buffer.find('.') == buffer.npos && buffer.find('e') == buffer.npos) {
|
||||||
buffer += ".0";
|
buffer += ".0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// strip the zero padding from the right
|
||||||
|
if (precisionType == PrecisionType::decimalPlaces) {
|
||||||
|
buffer.erase(fixZerosInTheEnd(buffer.begin(), buffer.end(), precision),
|
||||||
|
buffer.end());
|
||||||
|
}
|
||||||
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -173,16 +115,12 @@ String valueToString(double value, unsigned int precision,
|
|||||||
|
|
||||||
String valueToString(bool value) { return value ? "true" : "false"; }
|
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);
|
assert(s || !n);
|
||||||
|
|
||||||
char const* const end = s + n;
|
return std::any_of(s, s + n, [](unsigned char c) {
|
||||||
for (char const* cur = s; cur < end; ++cur) {
|
return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
|
||||||
if (*cur == '\\' || *cur == '\"' || *cur < ' ' ||
|
});
|
||||||
static_cast<unsigned char>(*cur) < 0x80)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
|
static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
|
||||||
@@ -264,12 +202,20 @@ static String toHex16Bit(unsigned int x) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String valueToQuotedStringN(const char* value, unsigned length,
|
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, size_t length,
|
||||||
bool emitUTF8 = false) {
|
bool emitUTF8 = false) {
|
||||||
if (value == nullptr)
|
if (value == nullptr)
|
||||||
return "";
|
return "";
|
||||||
|
|
||||||
if (!isAnyCharRequiredQuoting(value, length))
|
if (!doesAnyCharRequireEscaping(value, length))
|
||||||
return String("\"") + value + "\"";
|
return String("\"") + value + "\"";
|
||||||
// We have to walk value and escape any special characters.
|
// We have to walk value and escape any special characters.
|
||||||
// Appending to String is not efficient, but this should be rare.
|
// Appending to String is not efficient, but this should be rare.
|
||||||
@@ -312,29 +258,26 @@ static String valueToQuotedStringN(const char* value, unsigned length,
|
|||||||
// sequence from occurring.
|
// sequence from occurring.
|
||||||
default: {
|
default: {
|
||||||
if (emitUTF8) {
|
if (emitUTF8) {
|
||||||
result += *c;
|
unsigned codepoint = static_cast<unsigned char>(*c);
|
||||||
|
if (codepoint < 0x20) {
|
||||||
|
appendHex(result, codepoint);
|
||||||
|
} else {
|
||||||
|
appendRaw(result, codepoint);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned int codepoint = utf8ToCodepoint(c, end);
|
unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
|
||||||
const unsigned int FIRST_NON_CONTROL_CODEPOINT = 0x20;
|
if (codepoint < 0x20) {
|
||||||
const unsigned int LAST_NON_CONTROL_CODEPOINT = 0x7F;
|
appendHex(result, codepoint);
|
||||||
const unsigned int FIRST_SURROGATE_PAIR_CODEPOINT = 0x10000;
|
} else if (codepoint < 0x80) {
|
||||||
// don't escape non-control characters
|
appendRaw(result, codepoint);
|
||||||
// (short escape sequence are applied above)
|
} else if (codepoint < 0x10000) {
|
||||||
if (FIRST_NON_CONTROL_CODEPOINT <= codepoint &&
|
// Basic Multilingual Plane
|
||||||
codepoint <= LAST_NON_CONTROL_CODEPOINT) {
|
appendHex(result, codepoint);
|
||||||
result += static_cast<char>(codepoint);
|
} else {
|
||||||
} else if (codepoint <
|
// Extended Unicode. Encode 20 bits as a surrogate pair.
|
||||||
FIRST_SURROGATE_PAIR_CODEPOINT) { // codepoint is in Basic
|
codepoint -= 0x10000;
|
||||||
// Multilingual Plane
|
appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
|
||||||
result += "\\u";
|
appendHex(result, 0xdc00 + (codepoint & 0x3ff));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -345,7 +288,11 @@ static String valueToQuotedStringN(const char* value, unsigned length,
|
|||||||
}
|
}
|
||||||
|
|
||||||
String valueToQuotedString(const char* value) {
|
String valueToQuotedString(const char* value) {
|
||||||
return valueToQuotedStringN(value, static_cast<unsigned int>(strlen(value)));
|
return valueToQuotedStringN(value, strlen(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
String valueToQuotedString(const char* value, size_t length) {
|
||||||
|
return valueToQuotedStringN(value, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Class Writer
|
// Class Writer
|
||||||
@@ -394,7 +341,7 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
if (ok)
|
if (ok)
|
||||||
document_ += valueToQuotedStringN(str, static_cast<unsigned>(end - str));
|
document_ += valueToQuotedStringN(str, static_cast<size_t>(end - str));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
@@ -417,8 +364,7 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
if (it != members.begin())
|
if (it != members.begin())
|
||||||
document_ += ',';
|
document_ += ',';
|
||||||
document_ += valueToQuotedStringN(name.data(),
|
document_ += valueToQuotedStringN(name.data(), name.length());
|
||||||
static_cast<unsigned>(name.length()));
|
|
||||||
document_ += yamlCompatibilityEnabled_ ? ": " : ":";
|
document_ += yamlCompatibilityEnabled_ ? ": " : ":";
|
||||||
writeValue(value[name]);
|
writeValue(value[name]);
|
||||||
}
|
}
|
||||||
@@ -463,7 +409,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
if (ok)
|
if (ok)
|
||||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
|
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
|
||||||
else
|
else
|
||||||
pushValue("");
|
pushValue("");
|
||||||
break;
|
break;
|
||||||
@@ -486,7 +432,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedString(name.c_str()));
|
writeWithIndent(valueToQuotedString(name.c_str(), name.size()));
|
||||||
document_ += " : ";
|
document_ += " : ";
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@@ -504,7 +450,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void StyledWriter::writeArrayValue(const Value& value) {
|
void StyledWriter::writeArrayValue(const Value& value) {
|
||||||
unsigned size = value.size();
|
size_t size = value.size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
pushValue("[]");
|
pushValue("[]");
|
||||||
else {
|
else {
|
||||||
@@ -513,7 +459,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
|
|||||||
writeWithIndent("[");
|
writeWithIndent("[");
|
||||||
indent();
|
indent();
|
||||||
bool hasChildValue = !childValues_.empty();
|
bool hasChildValue = !childValues_.empty();
|
||||||
unsigned index = 0;
|
ArrayIndex index = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const Value& childValue = value[index];
|
const Value& childValue = value[index];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
@@ -536,7 +482,7 @@ void StyledWriter::writeArrayValue(const Value& value) {
|
|||||||
{
|
{
|
||||||
assert(childValues_.size() == size);
|
assert(childValues_.size() == size);
|
||||||
document_ += "[ ";
|
document_ += "[ ";
|
||||||
for (unsigned index = 0; index < size; ++index) {
|
for (size_t index = 0; index < size; ++index) {
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
document_ += ", ";
|
document_ += ", ";
|
||||||
document_ += childValues_[index];
|
document_ += childValues_[index];
|
||||||
@@ -681,7 +627,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
if (ok)
|
if (ok)
|
||||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str)));
|
pushValue(valueToQuotedStringN(str, static_cast<size_t>(end - str)));
|
||||||
else
|
else
|
||||||
pushValue("");
|
pushValue("");
|
||||||
break;
|
break;
|
||||||
@@ -704,7 +650,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
const String& name = *it;
|
const String& name = *it;
|
||||||
const Value& childValue = value[name];
|
const Value& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedString(name.c_str()));
|
writeWithIndent(valueToQuotedString(name.c_str(), name.size()));
|
||||||
*document_ << " : ";
|
*document_ << " : ";
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@@ -955,8 +901,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
if (ok)
|
if (ok)
|
||||||
pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end - str),
|
pushValue(
|
||||||
emitUTF8_));
|
valueToQuotedStringN(str, static_cast<size_t>(end - str), emitUTF8_));
|
||||||
else
|
else
|
||||||
pushValue("");
|
pushValue("");
|
||||||
break;
|
break;
|
||||||
@@ -979,8 +925,8 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
String const& name = *it;
|
String const& name = *it;
|
||||||
Value const& childValue = value[name];
|
Value const& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedStringN(
|
writeWithIndent(
|
||||||
name.data(), static_cast<unsigned>(name.length()), emitUTF8_));
|
valueToQuotedStringN(name.data(), name.length(), emitUTF8_));
|
||||||
*sout_ << colonSymbol_;
|
*sout_ << colonSymbol_;
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@@ -1197,34 +1143,30 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
|
|||||||
endingLineFeedSymbol, usf, emitUTF8, pre,
|
endingLineFeedSymbol, usf, emitUTF8, pre,
|
||||||
precisionType);
|
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 {
|
bool StreamWriterBuilder::validate(Json::Value* invalid) const {
|
||||||
Json::Value my_invalid;
|
static const auto& valid_keys = *new std::set<String>{
|
||||||
if (!invalid)
|
"indentation",
|
||||||
invalid = &my_invalid; // so we do not need to test for NULL
|
"commentStyle",
|
||||||
Json::Value& inv = *invalid;
|
"enableYAMLCompatibility",
|
||||||
std::set<String> valid_keys;
|
"dropNullPlaceholders",
|
||||||
getValidWriterKeys(&valid_keys);
|
"useSpecialFloats",
|
||||||
Value::Members keys = settings_.getMemberNames();
|
"emitUTF8",
|
||||||
size_t n = keys.size();
|
"precision",
|
||||||
for (size_t i = 0; i < n; ++i) {
|
"precisionType",
|
||||||
String const& key = keys[i];
|
};
|
||||||
if (valid_keys.find(key) == valid_keys.end()) {
|
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
|
||||||
inv[key] = settings_[key];
|
auto key = si.name();
|
||||||
}
|
if (valid_keys.count(key))
|
||||||
|
continue;
|
||||||
|
if (invalid)
|
||||||
|
(*invalid)[key] = *si;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return inv.empty();
|
return invalid ? invalid->empty() : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& StreamWriterBuilder::operator[](const String& key) {
|
Value& StreamWriterBuilder::operator[](const String& key) {
|
||||||
return settings_[key];
|
return settings_[key];
|
||||||
}
|
}
|
||||||
@@ -1246,7 +1188,7 @@ String writeString(StreamWriter::Factory const& factory, Value const& root) {
|
|||||||
OStringStream sout;
|
OStringStream sout;
|
||||||
StreamWriterPtr const writer(factory.newStreamWriter());
|
StreamWriterPtr const writer(factory.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
return sout.str();
|
return std::move(sout).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
OStream& operator<<(OStream& sout, Value const& root) {
|
OStream& operator<<(OStream& sout, Value const& root) {
|
||||||
|
@@ -1,46 +1,39 @@
|
|||||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
|
||||||
add_executable( jsoncpp_test
|
add_executable(jsoncpp_test
|
||||||
jsontest.cpp
|
jsontest.cpp
|
||||||
jsontest.h
|
jsontest.h
|
||||||
fuzz.cpp
|
fuzz.cpp
|
||||||
fuzz.h
|
fuzz.h
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if(BUILD_SHARED_LIBS)
|
if(BUILD_SHARED_LIBS)
|
||||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
|
||||||
add_compile_definitions( JSON_DLL )
|
add_compile_definitions( JSON_DLL )
|
||||||
else()
|
else()
|
||||||
add_definitions( -DJSON_DLL )
|
add_definitions( -DJSON_DLL )
|
||||||
endif()
|
endif()
|
||||||
|
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
||||||
|
else()
|
||||||
|
target_link_libraries(jsoncpp_test jsoncpp_static)
|
||||||
endif()
|
endif()
|
||||||
target_link_libraries(jsoncpp_test jsoncpp_lib)
|
|
||||||
|
|
||||||
# another way to solve issue #90
|
# another way to solve issue #90
|
||||||
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
|
#set_target_properties(jsoncpp_test PROPERTIES COMPILE_FLAGS -ffloat-store)
|
||||||
|
|
||||||
|
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
||||||
|
add_test(NAME jsoncpp_test
|
||||||
|
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
||||||
|
)
|
||||||
|
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
||||||
|
|
||||||
# Run unit tests in post-build
|
# Run unit tests in post-build
|
||||||
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
# (default cmake workflow hides away the test result into a file, resulting in poor dev workflow?!?)
|
||||||
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
if(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
||||||
if(BUILD_SHARED_LIBS)
|
add_custom_command(TARGET jsoncpp_test
|
||||||
# First, copy the shared lib, for Microsoft.
|
POST_BUILD
|
||||||
# Then, run the test executable.
|
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
||||||
add_custom_command( TARGET jsoncpp_test
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:jsoncpp_lib> $<TARGET_FILE_DIR:jsoncpp_test>
|
|
||||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
|
|
||||||
else(BUILD_SHARED_LIBS)
|
|
||||||
# Just run the test executable.
|
|
||||||
add_custom_command( TARGET jsoncpp_test
|
|
||||||
POST_BUILD
|
|
||||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>)
|
|
||||||
endif()
|
|
||||||
## Create tests for dashboard submission, allows easy review of CI results https://my.cdash.org/index.php?project=jsoncpp
|
|
||||||
add_test(NAME jsoncpp_test
|
|
||||||
COMMAND ${CMAKE_CROSSCOMPILING_EMULATOR} $<TARGET_FILE:jsoncpp_test>
|
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
|
||||||
|
@@ -9,7 +9,6 @@
|
|||||||
#include <json/config.h>
|
#include <json/config.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <stdint.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
@@ -40,11 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
|||||||
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
|
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
|
||||||
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
|
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
|
||||||
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
builder.settings_["collectComments"] = hash_settings & (1 << 9);
|
||||||
|
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
|
||||||
|
|
||||||
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
|
||||||
|
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
const char* data_str = reinterpret_cast<const char*>(data);
|
const auto data_str = reinterpret_cast<const char*>(data);
|
||||||
try {
|
try {
|
||||||
reader->parse(data_str, data_str + size, &root, nullptr);
|
reader->parse(data_str, data_str + size, &root, nullptr);
|
||||||
} catch (Json::Exception const&) {
|
} catch (Json::Exception const&) {
|
||||||
|
@@ -267,19 +267,18 @@ bool Runner::runAllTest(bool printSummary) const {
|
|||||||
printf("All %zu tests passed\n", count);
|
printf("All %zu tests passed\n", count);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
for (auto& result : failures) {
|
|
||||||
result.printFailure(count > 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printSummary) {
|
|
||||||
size_t const failedCount = failures.size();
|
|
||||||
size_t const passedCount = count - failedCount;
|
|
||||||
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
|
|
||||||
failedCount);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
for (auto& result : failures) {
|
||||||
|
result.printFailure(count > 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (printSummary) {
|
||||||
|
size_t const failedCount = failures.size();
|
||||||
|
size_t const passedCount = count - failedCount;
|
||||||
|
printf("%zu/%zu tests passed (%zu failure(s))\n", passedCount, count,
|
||||||
|
failedCount);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
|
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
|
||||||
@@ -308,7 +307,8 @@ int Runner::runCommandLine(int argc, const char* argv[]) const {
|
|||||||
if (opt == "--list-tests") {
|
if (opt == "--list-tests") {
|
||||||
listTests();
|
listTests();
|
||||||
return 0;
|
return 0;
|
||||||
} else if (opt == "--test-auto") {
|
}
|
||||||
|
if (opt == "--test-auto") {
|
||||||
preventDialogOnCrash();
|
preventDialogOnCrash();
|
||||||
} else if (opt == "--test") {
|
} else if (opt == "--test") {
|
||||||
++index;
|
++index;
|
||||||
@@ -410,7 +410,7 @@ Json::String ToJsonString(const char* toConvert) {
|
|||||||
|
|
||||||
Json::String ToJsonString(Json::String in) { return in; }
|
Json::String ToJsonString(Json::String in) { return in; }
|
||||||
|
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
Json::String ToJsonString(std::string in) {
|
Json::String ToJsonString(std::string in) {
|
||||||
return Json::String(in.data(), in.data() + in.length());
|
return Json::String(in.data(), in.data() + in.length());
|
||||||
}
|
}
|
||||||
|
@@ -42,7 +42,7 @@ public:
|
|||||||
/// Must be a POD to allow inline initialisation without stepping
|
/// Must be a POD to allow inline initialisation without stepping
|
||||||
/// into the debugger.
|
/// into the debugger.
|
||||||
struct PredicateContext {
|
struct PredicateContext {
|
||||||
typedef unsigned int Id;
|
using Id = unsigned int;
|
||||||
Id id_;
|
Id id_;
|
||||||
const char* file_;
|
const char* file_;
|
||||||
unsigned int line_;
|
unsigned int line_;
|
||||||
@@ -74,7 +74,7 @@ public:
|
|||||||
|
|
||||||
/// Removes the last PredicateContext added to the predicate stack
|
/// Removes the last PredicateContext added to the predicate stack
|
||||||
/// chained list.
|
/// chained list.
|
||||||
/// Next messages will be targed at the PredicateContext that was removed.
|
/// Next messages will be targeted at the PredicateContext that was removed.
|
||||||
TestResult& popPredicateContext();
|
TestResult& popPredicateContext();
|
||||||
|
|
||||||
bool failed() const;
|
bool failed() const;
|
||||||
@@ -102,7 +102,7 @@ private:
|
|||||||
static Json::String indentText(const Json::String& text,
|
static Json::String indentText(const Json::String& text,
|
||||||
const Json::String& indent);
|
const Json::String& indent);
|
||||||
|
|
||||||
typedef std::deque<Failure> Failures;
|
using Failures = std::deque<Failure>;
|
||||||
Failures failures_;
|
Failures failures_;
|
||||||
Json::String name_;
|
Json::String name_;
|
||||||
PredicateContext rootPredicateNode_;
|
PredicateContext rootPredicateNode_;
|
||||||
@@ -129,7 +129,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Function pointer type for TestCase factory
|
/// Function pointer type for TestCase factory
|
||||||
typedef TestCase* (*TestCaseFactory)();
|
using TestCaseFactory = TestCase* (*)();
|
||||||
|
|
||||||
class Runner {
|
class Runner {
|
||||||
public:
|
public:
|
||||||
@@ -168,7 +168,7 @@ private:
|
|||||||
static void preventDialogOnCrash();
|
static void preventDialogOnCrash();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::deque<TestCaseFactory> Factories;
|
using Factories = std::deque<TestCaseFactory>;
|
||||||
Factories tests_;
|
Factories tests_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -185,7 +185,7 @@ TestResult& checkEqual(TestResult& result, T expected, U actual,
|
|||||||
|
|
||||||
Json::String ToJsonString(const char* toConvert);
|
Json::String ToJsonString(const char* toConvert);
|
||||||
Json::String ToJsonString(Json::String in);
|
Json::String ToJsonString(Json::String in);
|
||||||
#if JSONCPP_USING_SECURE_MEMORY
|
#if JSONCPP_USE_SECURE_MEMORY
|
||||||
Json::String ToJsonString(std::string in);
|
Json::String ToJsonString(std::string in);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -207,7 +207,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
/// The predicate may do other assertions and be a member function of the
|
/// The predicate may do other assertions and be a member function of the
|
||||||
/// fixture.
|
/// fixture.
|
||||||
#define JSONTEST_ASSERT_PRED(expr) \
|
#define JSONTEST_ASSERT_PRED(expr) \
|
||||||
{ \
|
do { \
|
||||||
JsonTest::PredicateContext _minitest_Context = { \
|
JsonTest::PredicateContext _minitest_Context = { \
|
||||||
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
|
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
|
||||||
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
result_->predicateStackTail_->next_ = &_minitest_Context; \
|
||||||
@@ -215,7 +215,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
result_->predicateStackTail_ = &_minitest_Context; \
|
result_->predicateStackTail_ = &_minitest_Context; \
|
||||||
(expr); \
|
(expr); \
|
||||||
result_->popPredicateContext(); \
|
result_->popPredicateContext(); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
/// \brief Asserts that two values are equals.
|
/// \brief Asserts that two values are equals.
|
||||||
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
|
#define JSONTEST_ASSERT_EQUAL(expected, actual) \
|
||||||
@@ -230,7 +230,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
|
|
||||||
/// \brief Asserts that a given expression throws an exception
|
/// \brief Asserts that a given expression throws an exception
|
||||||
#define JSONTEST_ASSERT_THROWS(expr) \
|
#define JSONTEST_ASSERT_THROWS(expr) \
|
||||||
{ \
|
do { \
|
||||||
bool _threw = false; \
|
bool _threw = false; \
|
||||||
try { \
|
try { \
|
||||||
expr; \
|
expr; \
|
||||||
@@ -240,7 +240,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
|
|||||||
if (!_threw) \
|
if (!_threw) \
|
||||||
result_->addFailure(__FILE__, __LINE__, \
|
result_->addFailure(__FILE__, __LINE__, \
|
||||||
"expected exception thrown: " #expr); \
|
"expected exception thrown: " #expr); \
|
||||||
}
|
} while (0)
|
||||||
|
|
||||||
/// \brief Begin a fixture test case.
|
/// \brief Begin a fixture test case.
|
||||||
#define JSONTEST_FIXTURE(FixtureType, name) \
|
#define JSONTEST_FIXTURE(FixtureType, name) \
|
||||||
|
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.'}
|
4
test/data/fail_strict_comment_01.json
Normal file
4
test/data/fail_strict_comment_01.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"a": "aaa",
|
||||||
|
"b": "bbb" // comments not allowed in strict mode
|
||||||
|
}
|
4
test/data/fail_strict_comment_02.json
Normal file
4
test/data/fail_strict_comment_02.json
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"a": "aaa", // comments not allowed in strict mode
|
||||||
|
"b": "bbb"
|
||||||
|
}
|
3
test/data/fail_strict_comment_03.json
Normal file
3
test/data/fail_strict_comment_03.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"array" : [1, 2, 3 /* comments not allowed in strict mode */]
|
||||||
|
}
|
1
test/data/fail_test_array_02.json
Normal file
1
test/data/fail_test_array_02.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[1,,]
|
1
test/data/fail_test_object_01.json
Normal file
1
test/data/fail_test_object_01.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ "count" : 1234,, }
|
1
test/data/fail_test_object_02.json
Normal file
1
test/data/fail_test_object_02.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{"one": 1 /* } */ { "two" : 2 }
|
@@ -1,4 +1,4 @@
|
|||||||
[ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
[ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
|
||||||
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
|
||||||
"ccccccccccccccccccccccc",
|
"ccccccccccccccccccccccc",
|
||||||
"dddddddddddddddddddddddddddddddddddddddddddddddddddd" ]
|
"dddddddddddddddddddddddddddddddddddddddddddddddddddd" ]
|
@@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"count" : 1234,
|
"count" : 1234,
|
||||||
"name" : { "aka" : "T.E.S.T.", "id" : 123987 },
|
"name" : { "aka" : "T.E.S.T.", "id" : 123987 },
|
||||||
"attribute" : [
|
"attribute" : [
|
||||||
"random",
|
"random",
|
||||||
"short",
|
"short",
|
||||||
"bold",
|
"bold",
|
||||||
12,
|
12,
|
||||||
{ "height" : 7, "width" : 64 }
|
{ "height" : 7, "width" : 64 }
|
||||||
],
|
],
|
||||||
"test": { "1" :
|
"test": { "1" :
|
||||||
{ "2" :
|
{ "2" :
|
||||||
{ "3" : { "coord" : [ 1,2] }
|
{ "3" : { "coord" : [ 1,2] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
{
|
{
|
||||||
"count" : 1234,
|
"count" : 1234,
|
||||||
"name" : "test",
|
"name" : "test",
|
||||||
"attribute" : "random"
|
"attribute" : "random"
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
{
|
{
|
||||||
"" : 1234
|
"" : 1234
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,6 @@
|
|||||||
/* Comment before 'second'
|
/* Comment before 'second'
|
||||||
*/
|
*/
|
||||||
.second=2
|
.second=2
|
||||||
/* A comment at
|
/* A comment at
|
||||||
the end of the file.
|
the end of the file.
|
||||||
*/
|
*/
|
||||||
|
@@ -9,6 +9,6 @@
|
|||||||
"second" : 2
|
"second" : 2
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A comment at
|
/* A comment at
|
||||||
the end of the file.
|
the end of the file.
|
||||||
*/
|
*/
|
||||||
|
3
test/data/legacy_test_real_13.expected
Normal file
3
test/data/legacy_test_real_13.expected
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
.=[]
|
||||||
|
.[0]=-inf
|
||||||
|
.[1]=inf
|
1
test/data/legacy_test_real_13.json
Normal file
1
test/data/legacy_test_real_13.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[-1e+9999, 1e+9999]
|
2
test/data/test_array_08.expected
Normal file
2
test/data/test_array_08.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.=[]
|
||||||
|
.[0]=1
|
1
test/data/test_array_08.json
Normal file
1
test/data/test_array_08.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[1,]
|
2
test/data/test_object_05.expected
Normal file
2
test/data/test_object_05.expected
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
.={}
|
||||||
|
.count=1234
|
1
test/data/test_object_05.json
Normal file
1
test/data/test_object_05.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{ "count" : 1234, }
|
@@ -15,7 +15,7 @@ import types
|
|||||||
if len(sys.argv) != 2:
|
if len(sys.argv) != 2:
|
||||||
print("Usage: %s input-json-file", sys.argv[0])
|
print("Usage: %s input-json-file", sys.argv[0])
|
||||||
sys.exit(3)
|
sys.exit(3)
|
||||||
|
|
||||||
input_path = sys.argv[1]
|
input_path = sys.argv[1]
|
||||||
base_path = os.path.splitext(input_path)[0]
|
base_path = os.path.splitext(input_path)[0]
|
||||||
actual_path = base_path + '.actual'
|
actual_path = base_path + '.actual'
|
||||||
@@ -23,7 +23,7 @@ rewrite_path = base_path + '.rewrite'
|
|||||||
rewrite_actual_path = base_path + '.actual-rewrite'
|
rewrite_actual_path = base_path + '.actual-rewrite'
|
||||||
|
|
||||||
def valueTreeToString(fout, value, path = '.'):
|
def valueTreeToString(fout, value, path = '.'):
|
||||||
ty = type(value)
|
ty = type(value)
|
||||||
if ty is types.DictType:
|
if ty is types.DictType:
|
||||||
fout.write('%s={}\n' % path)
|
fout.write('%s={}\n' % path)
|
||||||
suffix = path[-1] != '.' and '.' or ''
|
suffix = path[-1] != '.' and '.' or ''
|
||||||
@@ -49,7 +49,7 @@ def valueTreeToString(fout, value, path = '.'):
|
|||||||
fout.write('%s=null\n' % path)
|
fout.write('%s=null\n' % path)
|
||||||
else:
|
else:
|
||||||
assert False and "Unexpected value type"
|
assert False and "Unexpected value type"
|
||||||
|
|
||||||
def parseAndSaveValueTree(input, actual_path):
|
def parseAndSaveValueTree(input, actual_path):
|
||||||
root = json.loads(input)
|
root = json.loads(input)
|
||||||
fout = file(actual_path, 'wt')
|
fout = file(actual_path, 'wt')
|
||||||
@@ -62,7 +62,7 @@ def rewriteValueTree(value, rewrite_path):
|
|||||||
#rewrite = rewrite[1:-1] # Somehow the string is quoted ! jsonpy bug ?
|
#rewrite = rewrite[1:-1] # Somehow the string is quoted ! jsonpy bug ?
|
||||||
file(rewrite_path, 'wt').write(rewrite + '\n')
|
file(rewrite_path, 'wt').write(rewrite + '\n')
|
||||||
return rewrite
|
return rewrite
|
||||||
|
|
||||||
input = file(input_path, 'rt').read()
|
input = file(input_path, 'rt').read()
|
||||||
root = parseAndSaveValueTree(input, actual_path)
|
root = parseAndSaveValueTree(input, actual_path)
|
||||||
rewrite = rewriteValueTree(json.write(root), rewrite_path)
|
rewrite = rewriteValueTree(json.write(root), rewrite_path)
|
||||||
|
@@ -62,6 +62,10 @@ def safeReadFile(path):
|
|||||||
except IOError as e:
|
except IOError as e:
|
||||||
return '<File "%s" is missing: %s>' % (path,e)
|
return '<File "%s" is missing: %s>' % (path,e)
|
||||||
|
|
||||||
|
class FailError(Exception):
|
||||||
|
def __init__(self, msg):
|
||||||
|
super(Exception, self).__init__(msg)
|
||||||
|
|
||||||
def runAllTests(jsontest_executable_path, input_dir = None,
|
def runAllTests(jsontest_executable_path, input_dir = None,
|
||||||
use_valgrind=False, with_json_checker=False,
|
use_valgrind=False, with_json_checker=False,
|
||||||
writerClass='StyledWriter'):
|
writerClass='StyledWriter'):
|
||||||
@@ -69,57 +73,41 @@ def runAllTests(jsontest_executable_path, input_dir = None,
|
|||||||
input_dir = os.path.join(os.getcwd(), 'data')
|
input_dir = os.path.join(os.getcwd(), 'data')
|
||||||
tests = glob(os.path.join(input_dir, '*.json'))
|
tests = glob(os.path.join(input_dir, '*.json'))
|
||||||
if with_json_checker:
|
if with_json_checker:
|
||||||
all_test_jsonchecker = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
|
all_tests = glob(os.path.join(input_dir, '../jsonchecker', '*.json'))
|
||||||
# These tests fail with strict json support, but pass with jsoncpp extra lieniency
|
# These tests fail with strict json support, but pass with JsonCPP's
|
||||||
"""
|
# extra leniency features. When adding a new exclusion to this list,
|
||||||
Failure details:
|
# remember to add the test's number and reasoning here:
|
||||||
* Test ../jsonchecker/fail25.json
|
known = ["fail{}.json".format(n) for n in [
|
||||||
Parsing should have failed:
|
4, 9, # fail because we allow trailing commas
|
||||||
[" tab character in string "]
|
7, # fails because we allow commas after close
|
||||||
|
8, # fails because we allow extra close
|
||||||
* Test ../jsonchecker/fail13.json
|
10, # fails because we allow extra values after close
|
||||||
Parsing should have failed:
|
13, # fails because we allow leading zeroes in numbers
|
||||||
{"Numbers cannot have leading zeroes": 013}
|
18, # fails because we allow deeply nested values
|
||||||
|
25, # fails because we allow tab characters in strings
|
||||||
* Test ../jsonchecker/fail18.json
|
27, # fails because we allow string line breaks
|
||||||
Parsing should have failed:
|
]]
|
||||||
[[[[[[[[[[[[[[[[[[[["Too deep"]]]]]]]]]]]]]]]]]]]]
|
test_jsonchecker = [ test for test in all_tests
|
||||||
|
if os.path.basename(test) not in known]
|
||||||
* Test ../jsonchecker/fail8.json
|
|
||||||
Parsing should have failed:
|
|
||||||
["Extra close"]]
|
|
||||||
|
|
||||||
* Test ../jsonchecker/fail7.json
|
|
||||||
Parsing should have failed:
|
|
||||||
["Comma after the close"],
|
|
||||||
|
|
||||||
* Test ../jsonchecker/fail10.json
|
|
||||||
Parsing should have failed:
|
|
||||||
{"Extra value after close": true} "misplaced quoted value"
|
|
||||||
|
|
||||||
* Test ../jsonchecker/fail27.json
|
|
||||||
Parsing should have failed:
|
|
||||||
["line
|
|
||||||
break"]
|
|
||||||
"""
|
|
||||||
known_differences_withjsonchecker = [ "fail25.json", "fail13.json", "fail18.json", "fail8.json",
|
|
||||||
"fail7.json", "fail10.json", "fail27.json" ]
|
|
||||||
test_jsonchecker = [ test for test in all_test_jsonchecker if os.path.basename(test) not in known_differences_withjsonchecker ]
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
test_jsonchecker = []
|
test_jsonchecker = []
|
||||||
|
|
||||||
failed_tests = []
|
failed_tests = []
|
||||||
valgrind_path = use_valgrind and VALGRIND_CMD or ''
|
valgrind_path = use_valgrind and VALGRIND_CMD or ''
|
||||||
for input_path in tests + test_jsonchecker:
|
for input_path in tests + test_jsonchecker:
|
||||||
expect_failure = os.path.basename(input_path).startswith('fail')
|
expect_failure = os.path.basename(input_path).startswith('fail')
|
||||||
is_json_checker_test = (input_path in test_jsonchecker) or expect_failure
|
is_json_checker_test = input_path in test_jsonchecker
|
||||||
|
is_parse_only = is_json_checker_test or expect_failure
|
||||||
|
is_strict_test = ('_strict_' in os.path.basename(input_path)) or is_json_checker_test
|
||||||
print('TESTING:', input_path, end=' ')
|
print('TESTING:', input_path, end=' ')
|
||||||
options = is_json_checker_test and '--json-checker' or ''
|
options = is_parse_only and '--parse-only' or ''
|
||||||
|
options += is_strict_test and ' --strict' or ''
|
||||||
options += ' --json-writer %s'%writerClass
|
options += ' --json-writer %s'%writerClass
|
||||||
cmd = '%s%s %s "%s"' % ( valgrind_path, jsontest_executable_path, options,
|
cmd = '%s%s %s "%s"' % ( valgrind_path, jsontest_executable_path, options,
|
||||||
input_path)
|
input_path)
|
||||||
status, process_output = getStatusOutput(cmd)
|
status, process_output = getStatusOutput(cmd)
|
||||||
if is_json_checker_test:
|
if is_parse_only:
|
||||||
if expect_failure:
|
if expect_failure:
|
||||||
if not status:
|
if not status:
|
||||||
print('FAILED')
|
print('FAILED')
|
||||||
@@ -161,10 +149,9 @@ def runAllTests(jsontest_executable_path, input_dir = None,
|
|||||||
print()
|
print()
|
||||||
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
|
print('Test results: %d passed, %d failed.' % (len(tests)-len(failed_tests),
|
||||||
len(failed_tests)))
|
len(failed_tests)))
|
||||||
return 1
|
raise FailError(repr(failed_tests))
|
||||||
else:
|
else:
|
||||||
print('All %d tests passed.' % len(tests))
|
print('All %d tests passed.' % len(tests))
|
||||||
return 0
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
@@ -187,24 +174,21 @@ def main():
|
|||||||
input_path = os.path.normpath(os.path.abspath(args[1]))
|
input_path = os.path.normpath(os.path.abspath(args[1]))
|
||||||
else:
|
else:
|
||||||
input_path = None
|
input_path = None
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledWriter')
|
writerClass='StyledWriter')
|
||||||
if status:
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
sys.exit(status)
|
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='StyledStreamWriter')
|
writerClass='StyledStreamWriter')
|
||||||
if status:
|
runAllTests(jsontest_executable_path, input_path,
|
||||||
sys.exit(status)
|
|
||||||
status = runAllTests(jsontest_executable_path, input_path,
|
|
||||||
use_valgrind=options.valgrind,
|
use_valgrind=options.valgrind,
|
||||||
with_json_checker=options.with_json_checker,
|
with_json_checker=options.with_json_checker,
|
||||||
writerClass='BuiltStyledStreamWriter')
|
writerClass='BuiltStyledStreamWriter')
|
||||||
if status:
|
|
||||||
sys.exit(status)
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
try:
|
||||||
|
main()
|
||||||
|
except FailError:
|
||||||
|
sys.exit(1)
|
||||||
|
Reference in New Issue
Block a user