mirror of
https://github.com/open-source-parsers/jsoncpp.git
synced 2025-10-15 15:16:47 +02:00
Compare commits
322 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
a679dde58d | ||
![]() |
c21b4bbfdb | ||
![]() |
d14d8c35c3 | ||
![]() |
ed258de63d | ||
![]() |
154652ee7a | ||
![]() |
4a9d77bcf7 | ||
![]() |
56efb6ba83 | ||
![]() |
7f9cc2705c | ||
![]() |
d7347a2623 | ||
![]() |
2e319850d1 | ||
![]() |
a3d35d7fb8 | ||
![]() |
19fc55f408 | ||
![]() |
acf74290f1 | ||
![]() |
746ef154f1 | ||
![]() |
559b4416e6 | ||
![]() |
6ca374371e | ||
![]() |
f7df408a6a | ||
![]() |
86ed860c4b | ||
![]() |
c442fd96e6 | ||
![]() |
c68443f3a0 | ||
![]() |
11c48d0047 | ||
![]() |
264c3edca7 | ||
![]() |
a47fc398ef | ||
![]() |
2f178f390f | ||
![]() |
f251f15e6a | ||
![]() |
60bfcf1715 | ||
![]() |
81065748e3 | ||
![]() |
11836ae9aa | ||
![]() |
e25fb5384a | ||
![]() |
f700fe4559 | ||
![]() |
d167a09b1c | ||
![]() |
ba158fd22d | ||
![]() |
f3a4941590 | ||
![]() |
0d25d9aebf | ||
![]() |
5021e799dc | ||
![]() |
762ad0fe9d | ||
![]() |
d6e666f573 | ||
![]() |
2ecd2a59de | ||
![]() |
a691cb19de | ||
![]() |
ee7935986e | ||
![]() |
b4abc8241f | ||
![]() |
12e9ef32f9 | ||
![]() |
77632b2611 | ||
![]() |
89aa87bd24 | ||
![]() |
34fc0020c0 | ||
![]() |
f880a9432d | ||
![]() |
5a82131033 | ||
![]() |
1839f2da34 | ||
![]() |
91c1d23461 | ||
![]() |
86f085b810 | ||
![]() |
ac372d2b00 | ||
![]() |
0e24e3c64f | ||
![]() |
89ab7eca7f | ||
![]() |
a1db52b030 | ||
![]() |
1572539bec | ||
![]() |
d8cd848ede | ||
![]() |
92259f7147 | ||
![]() |
4a431bcdac | ||
![]() |
7d868636de | ||
![]() |
ab0f1e234a | ||
![]() |
45a560a8c0 | ||
![]() |
4893a8f667 | ||
![]() |
f6d785fda8 | ||
![]() |
8d54e333ff | ||
![]() |
b063cf4ada | ||
![]() |
c4ab6d733f | ||
![]() |
2f97c0147b | ||
![]() |
52cfe5ae88 | ||
![]() |
a304d61a7b | ||
![]() |
0a97e38ea5 | ||
![]() |
894e78bff1 | ||
![]() |
126bdc2b05 | ||
![]() |
094a7d8564 | ||
![]() |
b9afdf190d | ||
![]() |
80a82ea269 | ||
![]() |
f78f685bab | ||
![]() |
7d8eddb98c | ||
![]() |
7e0571b444 | ||
![]() |
b14c8c1423 | ||
![]() |
b299d3581f | ||
![]() |
48d2a69d47 | ||
![]() |
772e257fc9 | ||
![]() |
101fcf0806 | ||
![]() |
7e4df50d17 | ||
![]() |
318f30357c | ||
![]() |
0f288aecdd | ||
![]() |
e0f9aab0bf | ||
![]() |
43203f1d09 | ||
![]() |
55176b2bdd | ||
![]() |
4356d9bba1 | ||
![]() |
ea4af18317 | ||
![]() |
b999616df8 | ||
![]() |
660307d357 | ||
![]() |
911e2b0fea | ||
![]() |
d4a49cf511 | ||
![]() |
8bd4f943da | ||
![]() |
4018422a05 | ||
![]() |
ba6fa48d31 | ||
![]() |
17fc9b1a80 | ||
![]() |
6f22b0e076 | ||
![]() |
980cdf0fb5 | ||
![]() |
45da594e71 | ||
![]() |
c8a7b445ea | ||
![]() |
c8054483f8 | ||
![]() |
96d32b37ea | ||
![]() |
ef2ff8754a | ||
![]() |
b58c844579 | ||
![]() |
b803b92d11 | ||
![]() |
98e981dff9 | ||
![]() |
1c47796479 | ||
![]() |
12c67e810d | ||
![]() |
c018d9fc3a | ||
![]() |
ae564653c4 | ||
![]() |
f8674c63b1 | ||
![]() |
b50a124fa6 | ||
![]() |
59e327f50b | ||
![]() |
0b597b4b48 | ||
![]() |
d97ea5bf8d | ||
![]() |
e29b671ed5 | ||
![]() |
fbe1cf3916 | ||
![]() |
cf86c473a5 | ||
![]() |
75570d7068 | ||
![]() |
5da29e2707 | ||
![]() |
c80faa400c | ||
![]() |
8aabf93cc1 | ||
![]() |
3e51598176 | ||
![]() |
1b5e61d008 | ||
![]() |
b84e0c159d | ||
![]() |
1e990640a9 | ||
![]() |
38bb491400 | ||
![]() |
724ba29bd3 | ||
![]() |
de5b792168 | ||
![]() |
1b8e3b7f4d | ||
![]() |
4878913143 | ||
![]() |
d179e24c14 | ||
![]() |
ccd70540e3 | ||
![]() |
b4d2b65841 | ||
![]() |
7e46bf76e8 | ||
![]() |
da0c50f7b2 | ||
![]() |
02bc3d77de | ||
![]() |
6b562c850d | ||
![]() |
2713f4f456 | ||
![]() |
83bc9c7cf6 | ||
![]() |
95f120f68e | ||
![]() |
9a4b1e39bf | ||
![]() |
2c872ec997 | ||
![]() |
b860cc38e8 | ||
![]() |
fef4b75796 | ||
![]() |
779d8a33fc | ||
![]() |
d4513fcf45 | ||
![]() |
baefec773c | ||
![]() |
bc72070f43 | ||
![]() |
bc9b445fee | ||
![]() |
2646ac5fa5 | ||
![]() |
2cca1cd239 | ||
![]() |
9234cbbc90 | ||
![]() |
7c93031c9b | ||
![]() |
48bfe91062 | ||
![]() |
0cce773019 | ||
![]() |
6b10ce8c0d | ||
![]() |
34bdbb58b4 | ||
![]() |
527965cbde | ||
![]() |
2b00891a86 | ||
![]() |
a4ce2829dc | ||
![]() |
69e7f1c858 | ||
![]() |
d1a2b94d5b | ||
![]() |
772f634548 | ||
![]() |
9fd1ca8d68 | ||
![]() |
38022157b2 | ||
![]() |
039a6e3b61 | ||
![]() |
9c17e61bd0 | ||
![]() |
c8a8cfcd4b | ||
![]() |
4994c77d09 | ||
![]() |
beae99924f | ||
![]() |
8b9940fd24 | ||
![]() |
b96d90efbd | ||
![]() |
e375b8c89e | ||
![]() |
49393ead06 | ||
![]() |
8df11d518b | ||
![]() |
8e400e9be7 | ||
![]() |
dc5aa4ad7f | ||
![]() |
80def66fa5 | ||
![]() |
6992831c1c | ||
![]() |
7e4875a239 | ||
![]() |
979cbec237 | ||
![]() |
2e625dd9af | ||
![]() |
83ea25e5e2 | ||
![]() |
5721f1ca57 | ||
![]() |
9942f6a1c7 | ||
![]() |
6c14548293 | ||
![]() |
6ee0bff822 | ||
![]() |
e3b35992f8 | ||
![]() |
cc5cdb565c | ||
![]() |
aadd0b1b63 | ||
![]() |
3ee15b7bcc | ||
![]() |
68509e6161 | ||
![]() |
4cea1f6f6c | ||
![]() |
6f9ed421d0 | ||
![]() |
7f7bbeff76 | ||
![]() |
bfffe8cec7 | ||
![]() |
73154fb546 | ||
![]() |
63c747218b | ||
![]() |
2084563efb | ||
![]() |
6329975e6d | ||
![]() |
7acfd599f0 | ||
![]() |
63a961a752 | ||
![]() |
cb2378fa41 | ||
![]() |
37aaaec70e | ||
![]() |
585446e6b3 | ||
![]() |
7f4be39e9f | ||
![]() |
47595e922b | ||
![]() |
9f7dbcb19b | ||
![]() |
c1996256d6 | ||
![]() |
25e4adc4e1 | ||
![]() |
cc2c15c3eb | ||
![]() |
912d55094d | ||
![]() |
d7b84f69c5 | ||
![]() |
9dad198af6 | ||
![]() |
7f06e9dc28 | ||
![]() |
d84702c903 | ||
![]() |
949babd7b0 | ||
![]() |
6ed877c77c | ||
![]() |
1c69568f8d | ||
![]() |
770fdda28b | ||
![]() |
81cf237917 | ||
![]() |
cac79543f8 | ||
![]() |
d8186f36a6 | ||
![]() |
7f240623d3 | ||
![]() |
784433ac72 | ||
![]() |
7275e3ce3c | ||
![]() |
46aa9d75fa | ||
![]() |
f94a0e8989 | ||
![]() |
e22a2f36f7 | ||
![]() |
fac87108a4 | ||
![]() |
14fc9f124e | ||
![]() |
658fa37e63 | ||
![]() |
056e5f9b64 | ||
![]() |
d8e8c14ffc | ||
![]() |
f4e6fccd46 | ||
![]() |
2428889813 | ||
![]() |
89704039a0 | ||
![]() |
6ca8ffcb91 | ||
![]() |
b5e70f950e | ||
![]() |
b26804d1c2 | ||
![]() |
702a539762 | ||
![]() |
81cb7e5c5b | ||
![]() |
d259f608fd | ||
![]() |
4652f818fe | ||
![]() |
ce32274ba5 | ||
![]() |
717c791d4e | ||
![]() |
6e52e272da | ||
![]() |
6416350438 | ||
![]() |
bcb83b921c | ||
![]() |
3f05b1a897 | ||
![]() |
de2c85f576 | ||
![]() |
b389d81bf9 | ||
![]() |
89c51f3457 | ||
![]() |
e6f1cffdd3 | ||
![]() |
64441486ac | ||
![]() |
d5e54d2609 | ||
![]() |
97e093a361 | ||
![]() |
d57ac97db8 | ||
![]() |
31e9962754 | ||
![]() |
5256551b03 | ||
![]() |
6649009ffa | ||
![]() |
2a10f4a3b8 | ||
![]() |
28d086e1d9 | ||
![]() |
a0a7c5f6de | ||
![]() |
fcbab02e4a | ||
![]() |
f4ee48bc21 | ||
![]() |
88184d142b | ||
![]() |
ae177fd901 | ||
![]() |
3f6345234f | ||
![]() |
a53070c42b | ||
![]() |
c09e121aeb | ||
![]() |
4f8ec9d207 | ||
![]() |
0fe61a68f8 | ||
![]() |
43019088f0 | ||
![]() |
0c1c076b7c | ||
![]() |
11130997c3 | ||
![]() |
30bb4ccb67 | ||
![]() |
74143f39e7 | ||
![]() |
56650e83c5 | ||
![]() |
441f8cdfa1 | ||
![]() |
a658759039 | ||
![]() |
0eb0e502c8 | ||
![]() |
e983204906 | ||
![]() |
fe06acb587 | ||
![]() |
1b49a55ea1 | ||
![]() |
13c36e9807 | ||
![]() |
50069d72da | ||
![]() |
24682e37bf | ||
![]() |
c2b988ee74 | ||
![]() |
e255ce31a4 | ||
![]() |
779b5bc5ba | ||
![]() |
63860617b3 | ||
![]() |
9cb88d2ca6 | ||
![]() |
363e51c0a9 | ||
![]() |
240ddb6a1b | ||
![]() |
9dd77dc0ef | ||
![]() |
244b1496e1 | ||
![]() |
c083835261 | ||
![]() |
cbe7e7c9cb | ||
![]() |
be183def8f | ||
![]() |
951bd3d05d | ||
![]() |
1c58876185 | ||
![]() |
2f2034629e | ||
![]() |
7020451b44 | ||
![]() |
80497f102e | ||
![]() |
f9feb66be2 | ||
![]() |
ed495edcc1 | ||
![]() |
3c0a383877 | ||
![]() |
5003983029 | ||
![]() |
871b311e7e | ||
![]() |
cdbc35f6ac | ||
![]() |
4e30c4fcdb | ||
![]() |
0d33cb3639 | ||
![]() |
2250b3c29d | ||
![]() |
9376368d86 | ||
![]() |
5383794cc9 | ||
![]() |
75279ccec2 | ||
![]() |
717b08695e |
11
.gitattributes
vendored
Normal file
11
.gitattributes
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
* text=auto
|
||||||
|
*.h text
|
||||||
|
*.cpp text
|
||||||
|
*.json text
|
||||||
|
*.in text
|
||||||
|
*.sh eol=lf
|
||||||
|
*.bat eol=crlf
|
||||||
|
*.vcproj eol=crlf
|
||||||
|
*.vcxproj eol=crlf
|
||||||
|
*.sln eol=crlf
|
||||||
|
devtools/agent_vm* eol=crlf
|
20
.gitignore
vendored
20
.gitignore
vendored
@@ -30,7 +30,23 @@
|
|||||||
|
|
||||||
# CMake-generated files:
|
# CMake-generated files:
|
||||||
CMakeFiles/
|
CMakeFiles/
|
||||||
CTestTestFile.cmake
|
*.cmake
|
||||||
cmake_install.cmake
|
|
||||||
pkg-config/jsoncpp.pc
|
pkg-config/jsoncpp.pc
|
||||||
jsoncpp_lib_static.dir/
|
jsoncpp_lib_static.dir/
|
||||||
|
|
||||||
|
# In case someone runs cmake in the root-dir:
|
||||||
|
/CMakeCache.txt
|
||||||
|
/Makefile
|
||||||
|
/include/Makefile
|
||||||
|
/src/Makefile
|
||||||
|
/src/jsontestrunner/Makefile
|
||||||
|
/src/jsontestrunner/jsontestrunner_exe
|
||||||
|
/src/lib_json/Makefile
|
||||||
|
/src/test_lib_json/Makefile
|
||||||
|
/src/test_lib_json/jsoncpp_test
|
||||||
|
*.a
|
||||||
|
|
||||||
|
# eclipse project files
|
||||||
|
.project
|
||||||
|
.cproject
|
||||||
|
/.settings/
|
||||||
|
50
.travis.yml
50
.travis.yml
@@ -2,16 +2,54 @@
|
|||||||
# http://about.travis-ci.org/docs/user/build-configuration/
|
# http://about.travis-ci.org/docs/user/build-configuration/
|
||||||
# This file can be validated on:
|
# This file can be validated on:
|
||||||
# http://lint.travis-ci.org/
|
# http://lint.travis-ci.org/
|
||||||
before_install: sudo apt-get install cmake
|
# See also
|
||||||
|
# http://stackoverflow.com/questions/22111549/travis-ci-with-clang-3-4-and-c11/30925448#30925448
|
||||||
|
# to allow C++11, though we are not yet building with -std=c++11
|
||||||
|
|
||||||
|
install:
|
||||||
|
- if [[ $TRAVIS_OS_NAME == osx ]]; then
|
||||||
|
brew update;
|
||||||
|
brew install python3 ninja;
|
||||||
|
python3 -m venv venv;
|
||||||
|
source venv/bin/activate;
|
||||||
|
elif [[ $TRAVIS_OS_NAME == linux ]]; then
|
||||||
|
wget https://github.com/ninja-build/ninja/releases/download/v1.7.2/ninja-linux.zip;
|
||||||
|
unzip -q ninja-linux.zip -d build;
|
||||||
|
fi
|
||||||
|
- pip3 install meson
|
||||||
|
# /usr/bin/gcc is 4.6 always, but gcc-X.Y is available.
|
||||||
|
- if [[ $CXX = g++ ]]; then export CXX="g++-4.9" CC="gcc-4.9"; fi
|
||||||
|
# /usr/bin/clang has a conflict with gcc, so use clang-X.Y.
|
||||||
|
- if [[ $CXX = clang++ ]]; then export CXX="clang++-3.5" CC="clang-3.5"; fi
|
||||||
|
- echo ${PATH}
|
||||||
|
- ls /usr/local
|
||||||
|
- ls /usr/local/bin
|
||||||
|
- export PATH="${PWD}"/build:/usr/local/bin:/usr/bin:${PATH}
|
||||||
|
- echo ${CXX}
|
||||||
|
- ${CXX} --version
|
||||||
|
- which valgrind
|
||||||
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- llvm-toolchain-precise-3.5
|
||||||
|
packages:
|
||||||
|
- gcc-4.9
|
||||||
|
- g++-4.9
|
||||||
|
- clang-3.5
|
||||||
|
- valgrind
|
||||||
|
os:
|
||||||
|
- linux
|
||||||
language: cpp
|
language: cpp
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
- clang
|
||||||
script: cmake -DJSONCPP_WITH_CMAKE_PACKAGE=$CMAKE_PKG -DJSONCPP_LIB_BUILD_SHARED=$SHARED_LIB -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=$VERBOSE_MAKE . && make && make jsoncpp_check
|
script: ./travis.sh
|
||||||
env:
|
env:
|
||||||
matrix:
|
matrix:
|
||||||
- SHARED_LIB=ON STATIC_LIB=ON CMAKE_PKG=ON BUILD_TYPE=release VERBOSE_MAKE=false
|
- LIB_TYPE=static BUILD_TYPE=release
|
||||||
- SHARED_LIB=OFF STATIC_LIB=ON CMAKE_PKG=OFF BUILD_TYPE=debug VERBOSE_MAKE=true VERBOSE
|
- LIB_TYPE=shared BUILD_TYPE=debug
|
||||||
notifications:
|
notifications:
|
||||||
email:
|
email: false
|
||||||
- aaronjjacobs@gmail.com
|
dist: trusty
|
||||||
|
sudo: false
|
||||||
|
110
AUTHORS
110
AUTHORS
@@ -1 +1,111 @@
|
|||||||
Baptiste Lepilleur <blep@users.sourceforge.net>
|
Baptiste Lepilleur <blep@users.sourceforge.net>
|
||||||
|
|
||||||
|
Aaron Jacobs <aaronjjacobs@gmail.com>
|
||||||
|
Aaron Jacobs <jacobsa@google.com>
|
||||||
|
Adam Boseley <ABoseley@agjunction.com>
|
||||||
|
Adam Boseley <adam.boseley@gmail.com>
|
||||||
|
Aleksandr Derbenev <13alexac@gmail.com>
|
||||||
|
Alexander Gazarov <DrMetallius@users.noreply.github.com>
|
||||||
|
Alexander V. Brezgin <abrezgin@appliedtech.ru>
|
||||||
|
Alexandr Brezgin <albrezgin@mail.ru>
|
||||||
|
Alexey Kruchinin <alexey@mopals.com>
|
||||||
|
Anton Indrawan <anton.indrawan@gmail.com>
|
||||||
|
Baptiste Jonglez <git@bitsofnetworks.org>
|
||||||
|
Baptiste Lepilleur <baptiste.lepilleur@gmail.com>
|
||||||
|
Baruch Siach <baruch@tkos.co.il>
|
||||||
|
Ben Boeckel <mathstuf@gmail.com>
|
||||||
|
Benjamin Knecht <bknecht@logitech.com>
|
||||||
|
Bernd Kuhls <bernd.kuhls@t-online.de>
|
||||||
|
Billy Donahue <billydonahue@google.com>
|
||||||
|
Braden McDorman <bmcdorman@gmail.com>
|
||||||
|
Brandon Myers <bmyers1788@gmail.com>
|
||||||
|
Brendan Drew <brendan.drew@daqri.com>
|
||||||
|
chason <cxchao802@gmail.com>
|
||||||
|
Chris Gilling <cgilling@iparadigms.com>
|
||||||
|
Christopher Dawes <christopher.dawes.1981@googlemail.com>
|
||||||
|
Christopher Dunn <cdunn2001@gmail.com>
|
||||||
|
Chuck Atkins <chuck.atkins@kitware.com>
|
||||||
|
Cody P Schafer <dev@codyps.com>
|
||||||
|
Connor Manning <connor@hobu.co>
|
||||||
|
Cory Quammen <cory.quammen@kitware.com>
|
||||||
|
Cristóvão B da Cruz e Silva <CrisXed@gmail.com>
|
||||||
|
Daniel Krügler <daniel.kruegler@gmail.com>
|
||||||
|
Dani-Hub <daniel.kruegler@googlemail.com>
|
||||||
|
Dan Liu <gzliudan>
|
||||||
|
datadiode <datadiode@users.noreply.github.com>
|
||||||
|
datadiode <jochen.neubeck@vodafone.de>
|
||||||
|
David Seifert <soap@gentoo.org>
|
||||||
|
David West <david-west@idexx.com>
|
||||||
|
dawesc <chris.dawes@eftlab.co.uk>
|
||||||
|
Dmitry Marakasov <amdmi3@amdmi3.ru>
|
||||||
|
dominicpezzuto <dom@dompezzuto.com>
|
||||||
|
Don Milham <dmilham@gmail.com>
|
||||||
|
drgler <daniel.kruegler@gmail.com>
|
||||||
|
ds283 <D.Seery@sussex.ac.uk>
|
||||||
|
Egor Tensin <Egor.Tensin@gmail.com>
|
||||||
|
eightnoteight <mr.eightnoteight@gmail.com>
|
||||||
|
Evince <baneyue@gmail.com>
|
||||||
|
filipjs <filipjs@users.noreply.github.com>
|
||||||
|
findblar <ft@finbarr.ca>
|
||||||
|
Florian Meier <florian.meier@koalo.de>
|
||||||
|
Gaëtan Lehmann <gaetan.lehmann@gmail.com>
|
||||||
|
Gaurav <g.gupta@samsung.com>
|
||||||
|
Gergely Nagy <ngg@ngg.hu>
|
||||||
|
Gida Pataki <gida.pataki@prezi.com>
|
||||||
|
I3ck <buckmartin@buckmartin.de>
|
||||||
|
Iñaki Baz Castillo <ibc@aliax.net>
|
||||||
|
Jacco <jacco@geul.net>
|
||||||
|
Jean-Christophe Fillion-Robin <jchris.fillionr@kitware.com>
|
||||||
|
Jonas Platte <mail@jonasplatte.de>
|
||||||
|
Jörg Krause <joerg.krause@embedded.rocks>
|
||||||
|
Keith Lea <keith@whamcitylights.com>
|
||||||
|
Kevin Grant <kbradleygrant@gmail.com>
|
||||||
|
Kirill V. Lyadvinsky <jia3ep@gmail.com>
|
||||||
|
Kirill V. Lyadvinsky <mail@codeatcpp.com>
|
||||||
|
Kobi Gurkan <kobigurk@gmail.com>
|
||||||
|
Magnus Bjerke Vik <mbvett@gmail.com>
|
||||||
|
Malay Shah <malays@users.sourceforge.net>
|
||||||
|
Mara Kim <hacker.root@gmail.com>
|
||||||
|
Marek Kotewicz <marek.kotewicz@gmail.com>
|
||||||
|
Mark Lakata <mark@lakata.org>
|
||||||
|
Mark Zeren <mzeren@vmware.com>
|
||||||
|
Martin Buck <buckmartin@buckmartin.de>
|
||||||
|
Martyn Gigg <martyn.gigg@gmail.com>
|
||||||
|
Mattes D <github@xoft.cz>
|
||||||
|
Matthias Loy <matthias.loy@hbm.com>
|
||||||
|
Merlyn Morgan-Graham <kavika@gmail.com>
|
||||||
|
Michael Shields <mshields@google.com>
|
||||||
|
Michał Górny <mgorny@gentoo.org>
|
||||||
|
Mike Naberezny <mike@naberezny.com>
|
||||||
|
mloy <matthias.loy@googlemail.com>
|
||||||
|
Motti <lanzkron@gmail.com>
|
||||||
|
nnkur <nnkur@mail.ru>
|
||||||
|
Omkar Wagh <owagh@owaghlinux.ny.tower-research.com>
|
||||||
|
paulo <paulobrizolara@users.noreply.github.com>
|
||||||
|
pavel.pimenov <pavel.pimenov@gmail.com>
|
||||||
|
Paweł Bylica <chfast@gmail.com>
|
||||||
|
Péricles Lopes Machado <pericles.raskolnikoff@gmail.com>
|
||||||
|
Peter Spiess-Knafl <psk@autistici.org>
|
||||||
|
pffang <pffang@vip.qq.com>
|
||||||
|
Rémi Verschelde <remi@verschelde.fr>
|
||||||
|
renu555 <renu.tyagi@samsung.com>
|
||||||
|
Robert Dailey <rcdailey@gmail.com>
|
||||||
|
Sam Clegg <sbc@chromium.org>
|
||||||
|
selaselah <selah@outlook.com>
|
||||||
|
Sergiy80 <sil2004@gmail.com>
|
||||||
|
sergzub <sergzub@gmail.com>
|
||||||
|
Stefan Schweter <stefan@schweter.it>
|
||||||
|
Steffen Kieß <Steffen.Kiess@ipvs.uni-stuttgart.de>
|
||||||
|
Steven Hahn <hahnse@ornl.gov>
|
||||||
|
Stuart Eichert <stuart@fivemicro.com>
|
||||||
|
SuperManitu <supermanitu@gmail.com>
|
||||||
|
Techwolf <dring@g33kworld.net>
|
||||||
|
Tengiz Sharafiev <btolfa+github@gmail.com>
|
||||||
|
Tomasz Maciejewski <tmaciejewsk@gmail.com>
|
||||||
|
Vicente Olivert Riera <Vincent.Riera@imgtec.com>
|
||||||
|
xiaoyur347 <xiaoyur347@gmail.com>
|
||||||
|
ycqiu <429148848@qq.com>
|
||||||
|
yiqiju <fred_ju@selinc.com>
|
||||||
|
Yu Xiaolei <dreifachstein@gmail.com>
|
||||||
|
|
||||||
|
Google Inc.
|
||||||
|
109
CMakeLists.txt
109
CMakeLists.txt
@@ -1,14 +1,17 @@
|
|||||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
|
||||||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8.5)
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.1)
|
||||||
PROJECT(jsoncpp)
|
PROJECT(jsoncpp)
|
||||||
ENABLE_TESTING()
|
ENABLE_TESTING()
|
||||||
|
|
||||||
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)
|
||||||
OPTION(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF)
|
OPTION(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occurs" OFF)
|
||||||
|
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" OFF)
|
OPTION(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" OFF)
|
||||||
|
OPTION(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF)
|
||||||
|
OPTION(BUILD_STATIC_LIBS "Build jsoncpp_lib static library." ON)
|
||||||
|
|
||||||
# Ensures that CMAKE_BUILD_TYPE is visible in cmake-gui on Unix
|
# Ensures that CMAKE_BUILD_TYPE is visible in cmake-gui on Unix
|
||||||
IF(NOT WIN32)
|
IF(NOT WIN32)
|
||||||
@@ -16,27 +19,23 @@ IF(NOT WIN32)
|
|||||||
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."
|
||||||
FORCE)
|
FORCE)
|
||||||
ENDIF(NOT CMAKE_BUILD_TYPE)
|
ENDIF()
|
||||||
ENDIF(NOT WIN32)
|
ENDIF()
|
||||||
|
|
||||||
SET(LIB_SUFFIX "" CACHE STRING "Optional arch-dependent suffix for the library installation directory")
|
# Enable runtime search path support for dynamic libraries on OSX
|
||||||
|
IF(APPLE)
|
||||||
|
SET(CMAKE_MACOSX_RPATH 1)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET(RUNTIME_INSTALL_DIR bin
|
# Adhere to GNU filesystem layout conventions
|
||||||
CACHE PATH "Install dir for executables and dlls")
|
INCLUDE(GNUInstallDirs)
|
||||||
SET(ARCHIVE_INSTALL_DIR lib${LIB_SUFFIX}
|
|
||||||
CACHE PATH "Install dir for static libraries")
|
SET(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build")
|
||||||
SET(LIBRARY_INSTALL_DIR lib${LIB_SUFFIX}
|
|
||||||
CACHE PATH "Install dir for shared libraries")
|
|
||||||
SET(INCLUDE_INSTALL_DIR include
|
|
||||||
CACHE PATH "Install dir for headers")
|
|
||||||
SET(PACKAGE_INSTALL_DIR lib${LIB_SUFFIX}/cmake
|
|
||||||
CACHE PATH "Install dir for cmake package config files")
|
|
||||||
MARK_AS_ADVANCED( RUNTIME_INSTALL_DIR ARCHIVE_INSTALL_DIR INCLUDE_INSTALL_DIR PACKAGE_INSTALL_DIR )
|
|
||||||
|
|
||||||
# Set variable named ${VAR_NAME} to value ${VALUE}
|
# Set variable named ${VAR_NAME} to value ${VALUE}
|
||||||
FUNCTION(set_using_dynamic_name VAR_NAME VALUE)
|
FUNCTION(set_using_dynamic_name VAR_NAME VALUE)
|
||||||
SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
|
SET( "${VAR_NAME}" "${VALUE}" PARENT_SCOPE)
|
||||||
ENDFUNCTION(set_using_dynamic_name)
|
ENDFUNCTION()
|
||||||
|
|
||||||
# Extract major, minor, patch from version text
|
# Extract major, minor, patch from version text
|
||||||
# Parse a version string "X.Y.Z" and outputs
|
# Parse a version string "X.Y.Z" and outputs
|
||||||
@@ -52,19 +51,21 @@ MACRO(jsoncpp_parse_version VERSION_TEXT OUPUT_PREFIX)
|
|||||||
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE )
|
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" TRUE )
|
||||||
ELSE( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
|
ELSE( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
|
||||||
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE )
|
set_using_dynamic_name( "${OUPUT_PREFIX}_FOUND" FALSE )
|
||||||
ENDIF( ${VERSION_TEXT} MATCHES ${VERSION_REGEX} )
|
ENDIF()
|
||||||
ENDMACRO(jsoncpp_parse_version)
|
ENDMACRO()
|
||||||
|
|
||||||
# Read out version from "version" file
|
# Read out version from "version" file
|
||||||
#FILE(STRINGS "version" JSONCPP_VERSION)
|
#FILE(STRINGS "version" JSONCPP_VERSION)
|
||||||
#SET( JSONCPP_VERSION_MAJOR X )
|
#SET( JSONCPP_VERSION_MAJOR X )
|
||||||
#SET( JSONCPP_VERSION_MINOR Y )
|
#SET( JSONCPP_VERSION_MINOR Y )
|
||||||
#SET( JSONCPP_VERSION_PATCH Z )
|
#SET( JSONCPP_VERSION_PATCH Z )
|
||||||
SET( JSONCPP_VERSION 1.5.4 )
|
SET( JSONCPP_VERSION 1.8.1 )
|
||||||
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
|
jsoncpp_parse_version( ${JSONCPP_VERSION} JSONCPP_VERSION )
|
||||||
#IF(NOT JSONCPP_VERSION_FOUND)
|
#IF(NOT JSONCPP_VERSION_FOUND)
|
||||||
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
|
# MESSAGE(FATAL_ERROR "Failed to parse version string properly. Expect X.Y.Z")
|
||||||
#ENDIF(NOT JSONCPP_VERSION_FOUND)
|
#ENDIF(NOT JSONCPP_VERSION_FOUND)
|
||||||
|
SET( JSONCPP_SOVERSION 11 )
|
||||||
|
SET( JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL" )
|
||||||
|
|
||||||
MESSAGE(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
|
MESSAGE(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}")
|
||||||
# File version.h is only regenerated on CMake configure step
|
# File version.h is only regenerated on CMake configure step
|
||||||
@@ -75,49 +76,81 @@ CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/version.in"
|
|||||||
"${PROJECT_SOURCE_DIR}/version"
|
"${PROJECT_SOURCE_DIR}/version"
|
||||||
NEWLINE_STYLE UNIX )
|
NEWLINE_STYLE UNIX )
|
||||||
|
|
||||||
macro(UseCompilationWarningAsError)
|
MACRO(UseCompilationWarningAsError)
|
||||||
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.
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
|
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
|
||||||
endif( MSVC )
|
ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
endmacro()
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
|
||||||
|
IF(JSONCPP_WITH_STRICT_ISO)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
|
||||||
|
ENDIF()
|
||||||
|
ENDIF()
|
||||||
|
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.
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
|
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
|
||||||
endif( MSVC )
|
ENDIF()
|
||||||
|
|
||||||
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
# Require C++11 support, prefer ISO C++ over GNU variants,
|
||||||
|
# as relying solely on ISO C++ is more portable.
|
||||||
|
SET(CMAKE_CXX_STANDARD 11)
|
||||||
|
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||||
|
SET(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
|
||||||
|
IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
# using regular Clang or AppleClang
|
# using regular Clang or AppleClang
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare")
|
||||||
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
|
ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||||
# using GCC
|
# using GCC
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -Wall -Wextra -pedantic")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
|
||||||
endif()
|
# not yet ready for -Wsign-conversion
|
||||||
|
|
||||||
|
IF(JSONCPP_WITH_STRICT_ISO)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||||
|
ENDIF()
|
||||||
|
IF(JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
|
||||||
|
ENDIF()
|
||||||
|
ELSEIF(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
|
||||||
|
# using Intel compiler
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
|
||||||
|
|
||||||
|
IF(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
|
||||||
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
|
||||||
|
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()
|
UseCompilationWarningAsError()
|
||||||
ENDIF(JSONCPP_WITH_WARNING_AS_ERROR)
|
ENDIF()
|
||||||
|
|
||||||
IF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
IF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
||||||
CONFIGURE_FILE(
|
CONFIGURE_FILE(
|
||||||
"pkg-config/jsoncpp.pc.in"
|
"pkg-config/jsoncpp.pc.in"
|
||||||
"pkg-config/jsoncpp.pc"
|
"pkg-config/jsoncpp.pc"
|
||||||
@ONLY)
|
@ONLY)
|
||||||
INSTALL(FILES "${CMAKE_BINARY_DIR}/pkg-config/jsoncpp.pc"
|
INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/pkg-config/jsoncpp.pc"
|
||||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}/pkgconfig")
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
ENDIF(JSONCPP_WITH_PKGCONFIG_SUPPORT)
|
ENDIF()
|
||||||
|
|
||||||
IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
INSTALL(EXPORT jsoncpp
|
INSTALL(EXPORT jsoncpp
|
||||||
DESTINATION ${PACKAGE_INSTALL_DIR}/jsoncpp
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
|
||||||
FILE jsoncppConfig.cmake)
|
FILE jsoncppConfig.cmake)
|
||||||
ENDIF(JSONCPP_WITH_CMAKE_PACKAGE)
|
ENDIF()
|
||||||
|
|
||||||
# Build the different applications
|
# Build the different applications
|
||||||
ADD_SUBDIRECTORY( src )
|
ADD_SUBDIRECTORY( src )
|
||||||
|
6
LICENSE
6
LICENSE
@@ -2,12 +2,12 @@ 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...
|
||||||
|
|
||||||
The author (Baptiste Lepilleur) explicitly disclaims copyright in all
|
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 is
|
2010), this software is Copyright (c) 2007-2010 by The JsonCpp Authors, and is
|
||||||
released under the terms of the MIT License (see below).
|
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
|
||||||
@@ -23,7 +23,7 @@ described in clear, concise terms at:
|
|||||||
The full text of the MIT License follows:
|
The full text of the MIT License follows:
|
||||||
|
|
||||||
========================================================================
|
========================================================================
|
||||||
Copyright (c) 2007-2010 Baptiste Lepilleur
|
Copyright (c) 2007-2010 The JsonCpp Authors
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person
|
Permission is hereby granted, free of charge, to any person
|
||||||
obtaining a copy of this software and associated documentation
|
obtaining a copy of this software and associated documentation
|
||||||
|
184
README.md
184
README.md
@@ -1,5 +1,6 @@
|
|||||||
Introduction
|
# JsonCpp
|
||||||
------------
|
|
||||||
|
[](http://www.conan.io/source/jsoncpp/1.8.0/theirix/ci)
|
||||||
|
|
||||||
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
[JSON][json-org] is a lightweight data-interchange format. It can represent
|
||||||
numbers, strings, ordered sequences of values, and collections of name/value
|
numbers, strings, ordered sequences of values, and collections of name/value
|
||||||
@@ -7,37 +8,109 @@ pairs.
|
|||||||
|
|
||||||
[json-org]: http://json.org/
|
[json-org]: http://json.org/
|
||||||
|
|
||||||
[JsonCpp][] is a C++ library that allows manipulating JSON values, including
|
JsonCpp is a C++ library that allows manipulating JSON values, including
|
||||||
serialization and deserialization to and from strings. It can also preserve
|
serialization and deserialization to and from strings. It can also preserve
|
||||||
existing comment in unserialization/serialization steps, making it a convenient
|
existing comment in unserialization/serialization steps, making it a convenient
|
||||||
format to store user input files.
|
format to store user input files.
|
||||||
|
|
||||||
[JsonCpp]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
[JsonCpp documentation][JsonCpp-documentation] is generated using [Doxygen][].
|
||||||
|
|
||||||
|
[JsonCpp-documentation]: http://open-source-parsers.github.io/jsoncpp-docs/doxygen/index.html
|
||||||
|
[Doxygen]: http://www.doxygen.org
|
||||||
|
|
||||||
|
|
||||||
## A note on backward-compatibility
|
## A note on backward-compatibility
|
||||||
|
|
||||||
* `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.
|
||||||
* Major versions maintain binary-compatibility.
|
* Major versions maintain binary-compatibility.
|
||||||
|
|
||||||
Using JsonCpp in your project
|
|
||||||
-----------------------------
|
|
||||||
The recommended approach to integrating JsonCpp in your project is to build
|
|
||||||
the amalgamated source (a single `.cpp` file) with your own build system. This
|
|
||||||
ensures consistency of compilation flags and ABI compatibility. See the section
|
|
||||||
"Generating amalgamated source and header" for instructions.
|
|
||||||
|
|
||||||
The `include/` should be added to your compiler include path. Jsoncpp headers
|
## Using JsonCpp in your project
|
||||||
|
|
||||||
|
The recommended approach to integrating JsonCpp in your project is to include
|
||||||
|
the [amalgamated source](#generating-amalgamated-source-and-header) (a single
|
||||||
|
`.cpp` file and two `.h` files) in your project, and compile and build as you
|
||||||
|
would any other source file. This ensures consistency of compilation flags and
|
||||||
|
ABI compatibility, issues which arise when building shared or static
|
||||||
|
libraries. See the next section for instructions.
|
||||||
|
|
||||||
|
The `include/` should be added to your compiler include path. JsonCpp headers
|
||||||
should be included as follow:
|
should be included as follow:
|
||||||
|
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
|
|
||||||
If JsonCpp was built as a dynamic library on Windows, then your project needs to
|
If JsonCpp was built as a dynamic library on Windows, then your project needs to define the macro `JSON_DLL`.
|
||||||
define the macro `JSON_DLL`.
|
|
||||||
|
|
||||||
Building and testing with CMake
|
### Generating amalgamated source and header
|
||||||
-------------------------------
|
|
||||||
[CMake][] is a C++ Makefiles/Solution generator. It is usually available on most
|
JsonCpp is provided with a script to generate a single header and a single
|
||||||
Linux system as package. On Ubuntu:
|
source file to ease inclusion into an existing project. The amalgamated source
|
||||||
|
can be generated at any time by running the following command from the
|
||||||
|
top-directory (this requires Python 2.6):
|
||||||
|
|
||||||
|
python amalgamate.py
|
||||||
|
|
||||||
|
It is possible to specify header name. See the `-h` option for detail.
|
||||||
|
|
||||||
|
By default, the following files are generated:
|
||||||
|
|
||||||
|
* `dist/jsoncpp.cpp`: source file that needs to be added to your project.
|
||||||
|
* `dist/json/json.h`: corresponding header file for use in your project. It is
|
||||||
|
equivalent to including `json/json.h` in non-amalgamated source. This header
|
||||||
|
only depends on standard headers.
|
||||||
|
* `dist/json/json-forwards.h`: header that provides forward declaration of all
|
||||||
|
JsonCpp types.
|
||||||
|
|
||||||
|
The amalgamated sources are generated by concatenating JsonCpp source in the
|
||||||
|
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion of other headers.
|
||||||
|
|
||||||
|
|
||||||
|
## Contributing to JsonCpp
|
||||||
|
|
||||||
|
### Building and testing with Conan
|
||||||
|
|
||||||
|
[Conan](https://www.conan.io/#/) is an open source package manager intended for C/C++ projects.
|
||||||
|
It is cross platform and build system agnostic.
|
||||||
|
|
||||||
|
Conan requires Python for running, and can be installed using pip:
|
||||||
|
|
||||||
|
pip install conan
|
||||||
|
|
||||||
|
Detailed instructions can be found on [conan docs](http://docs.conan.io/en/latest/).
|
||||||
|
|
||||||
|
For build jsoncpp with conan, you need to create a [conanfile.txt](http://docs.conan.io/en/latest/reference/conanfile_txt.html) or a [conanfile.py](http://docs.conan.io/en/latest/reference/conanfile.html). The first is simpler, but the second is more flexible.
|
||||||
|
|
||||||
|
This is a sample conanfile.txt:
|
||||||
|
|
||||||
|
```
|
||||||
|
[requires]
|
||||||
|
jsoncpp/1.8.0@theirix/ci
|
||||||
|
|
||||||
|
[generators]
|
||||||
|
cmake
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: cmake is not required, you can use other [integrations](http://docs.conan.io/en/latest/integrations.html). Or you can set the appropriate environment variables, using [virtualenv generators](http://docs.conan.io/en/latest/mastering/virtualenv.html).
|
||||||
|
|
||||||
|
Then run the following command from the conanfile directory:
|
||||||
|
|
||||||
|
conan install --build missing
|
||||||
|
|
||||||
|
This will try to download the appropriate package for your settings (OS, compiler, architecture) from the [recipe packages](https://www.conan.io/source/jsoncpp/1.8.0/theirix/ci). If it is not found, the package will be built.
|
||||||
|
|
||||||
|
**Note**: you do not need to install cmake to build jsoncpp using conan, because the recipe will download it automatically.
|
||||||
|
|
||||||
|
If you need, you can customize the jsoncpp recipe. Just clone/fork [it from github](https://github.com/theirix/conan-jsoncpp/).
|
||||||
|
|
||||||
|
See [integrations instructions](http://docs.conan.io/en/latest/integrations.html) for how to use your build system with conan.
|
||||||
|
|
||||||
|
### Building and testing with CMake
|
||||||
|
|
||||||
|
[CMake][] is a C++ Makefiles/Solution generator. It is usually available on most Linux system as package. On Ubuntu:
|
||||||
|
|
||||||
sudo apt-get install cmake
|
sudo apt-get install cmake
|
||||||
|
|
||||||
@@ -48,9 +121,9 @@ missing, the build will skip running those tests.
|
|||||||
|
|
||||||
When running CMake, a few parameters are required:
|
When running CMake, a few parameters are required:
|
||||||
|
|
||||||
* a build directory where the makefiles/solution are generated. It is also used
|
* A build directory where the makefiles/solution are generated. It is also used
|
||||||
to store objects, libraries and executables files.
|
to store objects, libraries and executables files.
|
||||||
* the generator to use: makefiles or Visual Studio solution? What version or
|
* The generator to use: makefiles or Visual Studio solution? What version or
|
||||||
Visual Studio, 32 or 64 bits solution?
|
Visual Studio, 32 or 64 bits solution?
|
||||||
|
|
||||||
Steps for generating solution/makefiles using `cmake-gui`:
|
Steps for generating solution/makefiles using `cmake-gui`:
|
||||||
@@ -58,7 +131,7 @@ Steps for generating solution/makefiles using `cmake-gui`:
|
|||||||
* Make "source code" point to the source directory.
|
* Make "source code" point to the source directory.
|
||||||
* Make "where to build the binary" point to the directory to use for the build.
|
* Make "where to build the binary" point to the directory to use for the build.
|
||||||
* Click on the "Grouped" check box.
|
* Click on the "Grouped" check box.
|
||||||
* Review JsonCpp build options (tick `JSONCPP_LIB_BUILD_SHARED` to build as a
|
* Review JsonCpp build options (tick `BUILD_SHARED_LIBS` to build as a
|
||||||
dynamic library).
|
dynamic library).
|
||||||
* Click the configure button at the bottom, then the generate button.
|
* Click the configure button at the bottom, then the generate button.
|
||||||
* The generated solution/makefiles can be found in the binary directory.
|
* The generated solution/makefiles can be found in the binary directory.
|
||||||
@@ -67,19 +140,23 @@ Alternatively, from the command-line on Unix in the source directory:
|
|||||||
|
|
||||||
mkdir -p build/debug
|
mkdir -p build/debug
|
||||||
cd build/debug
|
cd build/debug
|
||||||
cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_STATIC=ON -DJSONCPP_LIB_BUILD_SHARED=OFF -G "Unix Makefiles" ../..
|
cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_STATIC_LIBS=ON -DBUILD_SHARED_LIBS=OFF -DARCHIVE_INSTALL_DIR=. -G "Unix Makefiles" ../..
|
||||||
make
|
make
|
||||||
|
|
||||||
Running `cmake -`" will display the list of available generators (passed using
|
For a good pkg-config file, add:
|
||||||
|
|
||||||
|
-DCMAKE_INSTALL_INCLUDEDIR=include/jsoncpp
|
||||||
|
|
||||||
|
Running `cmake -h` will display the list of available generators (passed using
|
||||||
the `-G` option).
|
the `-G` option).
|
||||||
|
|
||||||
By default CMake hides compilation commands. This can be modified by specifying
|
By default CMake hides compilation commands. This can be modified by specifying
|
||||||
`-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles.
|
`-DCMAKE_VERBOSE_MAKEFILE=true` when generating makefiles.
|
||||||
|
|
||||||
Building and testing with SCons
|
### Building and testing with SCons
|
||||||
-------------------------------
|
|
||||||
**Note:** The SCons-based build system is deprecated. Please use CMake; see the
|
**Note:** The SCons-based build system is deprecated. Please use CMake (see the
|
||||||
section above.
|
section above).
|
||||||
|
|
||||||
JsonCpp can use [Scons][] as a build system. Note that SCons requires Python to
|
JsonCpp can use [Scons][] as a build system. Note that SCons requires Python to
|
||||||
be installed.
|
be installed.
|
||||||
@@ -106,7 +183,8 @@ If you are building with Microsoft Visual Studio 2008, you need to set up the
|
|||||||
environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before
|
environment by running `vcvars32.bat` (e.g. MSVC 2008 command prompt) before
|
||||||
running SCons.
|
running SCons.
|
||||||
|
|
||||||
# Running the tests manually
|
### Running the tests manually
|
||||||
|
|
||||||
You need to run tests manually only if you are troubleshooting an issue.
|
You need to run tests manually only if you are troubleshooting an issue.
|
||||||
|
|
||||||
In the instructions below, replace `path/to/jsontest` with the path of the
|
In the instructions below, replace `path/to/jsontest` with the path of the
|
||||||
@@ -129,44 +207,22 @@ In the instructions below, replace `path/to/jsontest` with the path of the
|
|||||||
# You can run the tests using valgrind:
|
# You can run the tests using valgrind:
|
||||||
python rununittests.py --valgrind path/to/test_lib_json
|
python rununittests.py --valgrind path/to/test_lib_json
|
||||||
|
|
||||||
## Running the tests using scons
|
### Running the tests using SCons
|
||||||
|
|
||||||
Note that tests can be run using SCons using the `check` target:
|
Note that tests can be run using SCons using the `check` target:
|
||||||
|
|
||||||
scons platform=$PLATFORM check
|
scons platform=$PLATFORM check
|
||||||
|
|
||||||
Building the documentation
|
### Building the documentation
|
||||||
--------------------------
|
|
||||||
Run the Python script `doxybuild.py` from the top directory:
|
Run the Python script `doxybuild.py` from the top directory:
|
||||||
|
|
||||||
python doxybuild.py --doxygen=$(which doxygen) --open --with-dot
|
python doxybuild.py --doxygen=$(which doxygen) --open --with-dot
|
||||||
|
|
||||||
See `doxybuild.py --help` for options.
|
See `doxybuild.py --help` for options.
|
||||||
|
|
||||||
Generating amalgamated source and header
|
### Adding a reader/writer test
|
||||||
----------------------------------------
|
|
||||||
JsonCpp is provided with a script to generate a single header and a single
|
|
||||||
source file to ease inclusion into an existing project. The amalgamated source
|
|
||||||
can be generated at any time by running the following command from the
|
|
||||||
top-directory (this requires Python 2.6):
|
|
||||||
|
|
||||||
python amalgamate.py
|
|
||||||
|
|
||||||
It is possible to specify header name. See the `-h` option for detail.
|
|
||||||
|
|
||||||
By default, the following files are generated:
|
|
||||||
* `dist/jsoncpp.cpp`: source file that needs to be added to your project.
|
|
||||||
* `dist/json/json.h`: corresponding header file for use in your project. It is
|
|
||||||
equivalent to including `json/json.h` in non-amalgamated source. This header
|
|
||||||
only depends on standard headers.
|
|
||||||
* `dist/json/json-forwards.h`: header that provides forward declaration of all
|
|
||||||
JsonCpp types.
|
|
||||||
|
|
||||||
The amalgamated sources are generated by concatenating JsonCpp source in the
|
|
||||||
correct order and defining the macro `JSON_IS_AMALGAMATION` to prevent inclusion
|
|
||||||
of other headers.
|
|
||||||
|
|
||||||
Adding a reader/writer test
|
|
||||||
---------------------------
|
|
||||||
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.
|
||||||
@@ -175,21 +231,19 @@ To add a test, you need to create two files in test/data:
|
|||||||
|
|
||||||
The `TESTNAME.expected` file format is as follows:
|
The `TESTNAME.expected` file format is as follows:
|
||||||
|
|
||||||
* each line represents a JSON element of the element tree represented by the
|
* Each line represents a JSON element of the element tree represented by the
|
||||||
input document.
|
input document.
|
||||||
* each line has two parts: the path to access the element separated from the
|
* Each line has two parts: the path to access the element separated from the
|
||||||
element value by `=`. Array and object values are always empty (i.e.
|
element value by `=`. Array and object values are always empty (i.e.
|
||||||
represented by either `[]` or `{}`).
|
represented by either `[]` or `{}`).
|
||||||
* element path: `.` represents the root element, and is used to separate object
|
* Element path `.` represents the root element, and is used to separate object
|
||||||
members. `[N]` is used to specify the value of an array element at index `N`.
|
members. `[N]` is used to specify the value of an array element at index `N`.
|
||||||
|
|
||||||
See the examples `test_complex_01.json` and `test_complex_01.expected` to better
|
See the examples `test_complex_01.json` and `test_complex_01.expected` to better understand element paths.
|
||||||
understand element paths.
|
|
||||||
|
|
||||||
Understanding reader/writer test output
|
### Understanding reader/writer test output
|
||||||
---------------------------------------
|
|
||||||
When a test is run, output files are generated beside the input test files.
|
When a test is run, output files are generated beside the input test files. Below is a short description of the content of each file:
|
||||||
Below is a short description of the content of each file:
|
|
||||||
|
|
||||||
* `test_complex_01.json`: input JSON document.
|
* `test_complex_01.json`: input JSON document.
|
||||||
* `test_complex_01.expected`: flattened JSON element tree used to check if
|
* `test_complex_01.expected`: flattened JSON element tree used to check if
|
||||||
@@ -204,7 +258,7 @@ Below is a short description of the content of each file:
|
|||||||
* `test_complex_01.process-output`: `jsontest` output, typically useful for
|
* `test_complex_01.process-output`: `jsontest` output, typically useful for
|
||||||
understanding parsing errors.
|
understanding parsing errors.
|
||||||
|
|
||||||
License
|
## License
|
||||||
-------
|
|
||||||
See the `LICENSE` file for details. In summary, JsonCpp is licensed under the
|
See the `LICENSE` file for details. In summary, JsonCpp is licensed under the
|
||||||
MIT license, or public domain if desired and recognized in your jurisdiction.
|
MIT license, or public domain if desired and recognized in your jurisdiction.
|
||||||
|
@@ -67,6 +67,7 @@ def amalgamate_source(source_top_dir=None,
|
|||||||
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("include/json/version.h")
|
header.add_file("include/json/version.h")
|
||||||
|
#header.add_file("include/json/allocator.h") # Not available here.
|
||||||
header.add_file("include/json/config.h")
|
header.add_file("include/json/config.h")
|
||||||
header.add_file("include/json/forwards.h")
|
header.add_file("include/json/forwards.h")
|
||||||
header.add_file("include/json/features.h")
|
header.add_file("include/json/features.h")
|
||||||
|
35
appveyor.yml
Normal file
35
appveyor.yml
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# This is a comment.
|
||||||
|
|
||||||
|
version: build.{build}
|
||||||
|
|
||||||
|
os: Windows Server 2012 R2
|
||||||
|
|
||||||
|
clone_folder: c:\projects\jsoncpp
|
||||||
|
|
||||||
|
platform:
|
||||||
|
- Win32
|
||||||
|
- x64
|
||||||
|
|
||||||
|
configuration:
|
||||||
|
- Debug
|
||||||
|
- Release
|
||||||
|
|
||||||
|
# scripts to run before build
|
||||||
|
before_build:
|
||||||
|
- echo "Running cmake..."
|
||||||
|
- cd c:\projects\jsoncpp
|
||||||
|
- cmake --version
|
||||||
|
- set PATH=C:\Program Files (x86)\MSBuild\14.0\Bin;%PATH%
|
||||||
|
- if %PLATFORM% == Win32 cmake .
|
||||||
|
- if %PLATFORM% == x64 cmake -G "Visual Studio 12 2013 Win64" .
|
||||||
|
|
||||||
|
build:
|
||||||
|
project: jsoncpp.sln # path to Visual Studio solution or project
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
provider: GitHub
|
||||||
|
auth_token:
|
||||||
|
secure: K2Tp1q8pIZ7rs0Ot24ZMWuwr12Ev6Tc6QkhMjGQxoQG3ng1pXtgPasiJ45IDXGdg
|
||||||
|
on:
|
||||||
|
branch: master
|
||||||
|
appveyor_repo_tag: true
|
@@ -16,7 +16,7 @@ dox:
|
|||||||
# Then 'git add -A' and 'git push' in jsoncpp-docs.
|
# Then 'git add -A' and 'git push' in jsoncpp-docs.
|
||||||
build:
|
build:
|
||||||
mkdir -p build/debug
|
mkdir -p build/debug
|
||||||
cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DJSONCPP_LIB_BUILD_SHARED=ON -G "Unix Makefiles" ../..
|
cd build/debug; cmake -DCMAKE_BUILD_TYPE=debug -DBUILD_SHARED_LIBS=ON -G "Unix Makefiles" ../..
|
||||||
make -C build/debug
|
make -C build/debug
|
||||||
|
|
||||||
# Currently, this depends on include/json/version.h generated
|
# Currently, this depends on include/json/version.h generated
|
||||||
@@ -26,6 +26,9 @@ test-amalgamate:
|
|||||||
python3.4 amalgamate.py
|
python3.4 amalgamate.py
|
||||||
cd dist; gcc -I. -c jsoncpp.cpp
|
cd dist; gcc -I. -c jsoncpp.cpp
|
||||||
|
|
||||||
|
valgrind:
|
||||||
|
valgrind --error-exitcode=42 --leak-check=full ./build/debug/src/test_lib_json/jsoncpp_test
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
\rm -rf *.gz *.asc dist/
|
\rm -rf *.gz *.asc dist/
|
||||||
|
|
||||||
|
@@ -1 +1,6 @@
|
|||||||
|
# Copyright 2010 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
|
||||||
|
|
||||||
# module
|
# module
|
@@ -19,8 +19,8 @@
|
|||||||
},
|
},
|
||||||
{"name": "shared_dll",
|
{"name": "shared_dll",
|
||||||
"variables": [
|
"variables": [
|
||||||
["JSONCPP_LIB_BUILD_SHARED=true"],
|
["BUILD_SHARED_LIBS=true"],
|
||||||
["JSONCPP_LIB_BUILD_SHARED=false"]
|
["BUILD_SHARED_LIBS=false"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{"name": "build_type",
|
{"name": "build_type",
|
||||||
|
@@ -12,8 +12,8 @@
|
|||||||
},
|
},
|
||||||
{"name": "shared_dll",
|
{"name": "shared_dll",
|
||||||
"variables": [
|
"variables": [
|
||||||
["JSONCPP_LIB_BUILD_SHARED=true"],
|
["BUILD_SHARED_LIBS=true"],
|
||||||
["JSONCPP_LIB_BUILD_SHARED=false"]
|
["BUILD_SHARED_LIBS=false"]
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{"name": "build_type",
|
{"name": "build_type",
|
||||||
|
@@ -1,6 +1,9 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# encoding: utf-8
|
# encoding: utf-8
|
||||||
# Baptiste Lepilleur, 2009
|
# Copyright 2009 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
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from dircache import listdir
|
from dircache import listdir
|
||||||
|
@@ -1,5 +1,11 @@
|
|||||||
|
# Copyright 2010 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
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os.path
|
import os.path
|
||||||
|
import sys
|
||||||
|
|
||||||
def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'):
|
def fix_source_eol(path, is_dry_run = True, verbose = True, eol = '\n'):
|
||||||
"""Makes sure that all sources have the specified eol sequence (default: unix)."""
|
"""Makes sure that all sources have the specified eol sequence (default: unix)."""
|
||||||
|
@@ -6,7 +6,7 @@ from __future__ import print_function
|
|||||||
# and ends with the first blank line.
|
# and ends with the first blank line.
|
||||||
LICENSE_BEGIN = "// Copyright "
|
LICENSE_BEGIN = "// Copyright "
|
||||||
|
|
||||||
BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 Baptiste Lepilleur
|
BRIEF_LICENSE = LICENSE_BEGIN + """2007-2010 The JsonCpp Authors
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// 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
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 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
|
||||||
|
|
||||||
from contextlib import closing
|
from contextlib import closing
|
||||||
import os
|
import os
|
||||||
import tarfile
|
import tarfile
|
||||||
|
@@ -31,7 +31,7 @@ def find_program(*filenames):
|
|||||||
paths = os.environ.get('PATH', '').split(os.pathsep)
|
paths = os.environ.get('PATH', '').split(os.pathsep)
|
||||||
suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or ''
|
suffixes = ('win32' in sys.platform) and '.exe .com .bat .cmd' or ''
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
for name in [filename+ext for ext in suffixes.split()]:
|
for name in [filename+ext for ext in suffixes.split(' ')]:
|
||||||
for directory in paths:
|
for directory in paths:
|
||||||
full_path = os.path.join(directory, name)
|
full_path = os.path.join(directory, name)
|
||||||
if os.path.isfile(full_path):
|
if os.path.isfile(full_path):
|
||||||
@@ -72,7 +72,7 @@ def run_cmd(cmd, silent=False):
|
|||||||
if silent:
|
if silent:
|
||||||
status, output = getstatusoutput(cmd)
|
status, output = getstatusoutput(cmd)
|
||||||
else:
|
else:
|
||||||
status, output = os.system(' '.join(cmd)), ''
|
status, output = subprocess.call(cmd), ''
|
||||||
if status:
|
if status:
|
||||||
msg = 'Error while %s ...\n\terror=%d, output="""%s"""' %(info, status, output)
|
msg = 'Error while %s ...\n\terror=%d, output="""%s"""' %(info, status, output)
|
||||||
raise Exception(msg)
|
raise Exception(msg)
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
FILE(GLOB INCLUDE_FILES "json/*.h")
|
FILE(GLOB INCLUDE_FILES "json/*.h")
|
||||||
INSTALL(FILES ${INCLUDE_FILES} DESTINATION ${INCLUDE_INSTALL_DIR}/json)
|
INSTALL(FILES ${INCLUDE_FILES} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/json)
|
||||||
|
98
include/json/allocator.h
Normal file
98
include/json/allocator.h
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
// Copyright 2007-2010 Baptiste Lepilleur
|
||||||
|
// 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 CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
#define CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
|
namespace Json {
|
||||||
|
template<typename T>
|
||||||
|
class SecureAllocator {
|
||||||
|
public:
|
||||||
|
// Type definitions
|
||||||
|
using value_type = T;
|
||||||
|
using pointer = T*;
|
||||||
|
using const_pointer = const T*;
|
||||||
|
using reference = T&;
|
||||||
|
using const_reference = const T&;
|
||||||
|
using size_type = std::size_t;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate memory for N items using the standard allocator.
|
||||||
|
*/
|
||||||
|
pointer allocate(size_type n) {
|
||||||
|
// allocate using "global operator new"
|
||||||
|
return static_cast<pointer>(::operator new(n * sizeof(T)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release memory which was allocated for N items at pointer P.
|
||||||
|
*
|
||||||
|
* The memory block is filled with zeroes before being released.
|
||||||
|
* The pointer argument is tagged as "volatile" to prevent the
|
||||||
|
* compiler optimizing out this critical step.
|
||||||
|
*/
|
||||||
|
void deallocate(volatile pointer p, size_type n) {
|
||||||
|
std::memset(p, 0, n * sizeof(T));
|
||||||
|
// free using "global operator delete"
|
||||||
|
::operator delete(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
template<typename... Args>
|
||||||
|
void construct(pointer p, Args&&... args) {
|
||||||
|
// construct using "placement new" and "perfect forwarding"
|
||||||
|
::new (static_cast<void*>(p)) T(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_type max_size() const {
|
||||||
|
return size_t(-1) / sizeof(T);
|
||||||
|
}
|
||||||
|
|
||||||
|
pointer address( reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
const_pointer address( const_reference x ) const {
|
||||||
|
return std::addressof(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroy an item in-place at pointer P.
|
||||||
|
*/
|
||||||
|
void destroy(pointer p) {
|
||||||
|
// destroy using "explicit destructor"
|
||||||
|
p->~T();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Boilerplate
|
||||||
|
SecureAllocator() {}
|
||||||
|
template<typename U> SecureAllocator(const SecureAllocator<U>&) {}
|
||||||
|
template<typename U> struct rebind { using other = SecureAllocator<U>; };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator==(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U>
|
||||||
|
bool operator!=(const SecureAllocator<T>&, const SecureAllocator<U>&) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} //namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
#endif // CPPTL_JSON_ALLOCATOR_H_INCLUDED
|
@@ -13,24 +13,32 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
/** It should not be possible for a maliciously designed file to
|
||||||
|
* cause an abort() or seg-fault, so these macros are used only
|
||||||
|
* for pre-condition violations and internal logic errors.
|
||||||
|
*/
|
||||||
#if JSON_USE_EXCEPTION
|
#if JSON_USE_EXCEPTION
|
||||||
#include <stdexcept>
|
|
||||||
#define JSON_ASSERT(condition) \
|
// @todo <= add detail about condition in exception
|
||||||
{if (!(condition)) {throw std::logic_error( "assert json failed" );}} // @todo <= add detail about condition in exception
|
# define JSON_ASSERT(condition) \
|
||||||
#define JSON_FAIL_MESSAGE(message) \
|
{if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
|
||||||
|
|
||||||
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
{ \
|
{ \
|
||||||
std::ostringstream oss; oss << message; \
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
throw std::logic_error(oss.str()); \
|
Json::throwLogicError(oss.str()); \
|
||||||
|
abort(); \
|
||||||
}
|
}
|
||||||
//#define JSON_FAIL_MESSAGE(message) throw std::logic_error(message)
|
|
||||||
#else // JSON_USE_EXCEPTION
|
#else // JSON_USE_EXCEPTION
|
||||||
#define JSON_ASSERT(condition) assert(condition)
|
|
||||||
|
# define JSON_ASSERT(condition) assert(condition)
|
||||||
|
|
||||||
// The call to assert() will show the failure message in debug builds. In
|
// The call to assert() will show the failure message in debug builds. In
|
||||||
// release bugs we abort, for a core-dump or debugger.
|
// release builds we abort, for a core-dump or debugger.
|
||||||
#define JSON_FAIL_MESSAGE(message) \
|
# define JSON_FAIL_MESSAGE(message) \
|
||||||
{ \
|
{ \
|
||||||
std::ostringstream oss; oss << message; \
|
JSONCPP_OSTRINGSTREAM oss; oss << message; \
|
||||||
assert(false && oss.str().c_str()); \
|
assert(false && oss.str().c_str()); \
|
||||||
abort(); \
|
abort(); \
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,9 @@
|
|||||||
|
|
||||||
#ifndef JSON_CONFIG_H_INCLUDED
|
#ifndef JSON_CONFIG_H_INCLUDED
|
||||||
#define JSON_CONFIG_H_INCLUDED
|
#define JSON_CONFIG_H_INCLUDED
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <string> //typedef String
|
||||||
|
#include <stdint.h> //typedef int64_t, uint64_t
|
||||||
|
|
||||||
/// If defined, indicates that json library is embedded in CppTL library.
|
/// If defined, indicates that json library is embedded in CppTL library.
|
||||||
//# define JSON_IN_CPPTL 1
|
//# define JSON_IN_CPPTL 1
|
||||||
@@ -37,12 +40,12 @@
|
|||||||
#ifdef JSON_IN_CPPTL
|
#ifdef JSON_IN_CPPTL
|
||||||
#define JSON_API CPPTL_API
|
#define JSON_API CPPTL_API
|
||||||
#elif defined(JSON_DLL_BUILD)
|
#elif defined(JSON_DLL_BUILD)
|
||||||
#if defined(_MSC_VER)
|
#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
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
#elif defined(JSON_DLL)
|
#elif defined(JSON_DLL)
|
||||||
#if defined(_MSC_VER)
|
#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)
|
||||||
@@ -56,26 +59,93 @@
|
|||||||
// Storages, and 64 bits integer support is disabled.
|
// Storages, and 64 bits integer support is disabled.
|
||||||
// #define JSON_NO_INT64 1
|
// #define JSON_NO_INT64 1
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER <= 1200 // MSVC 6
|
#if defined(_MSC_VER) // MSVC
|
||||||
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
# if _MSC_VER <= 1200 // MSVC 6
|
||||||
// (no conversion from unsigned __int64).
|
// Microsoft Visual Studio 6 only support conversion from __int64 to double
|
||||||
#define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
// (no conversion from unsigned __int64).
|
||||||
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
// characters in the debug information)
|
// Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
|
||||||
// All projects I've ever seen with VS6 were using this globally (not bothering
|
// characters in the debug information)
|
||||||
// with pragma push/pop).
|
// All projects I've ever seen with VS6 were using this globally (not bothering
|
||||||
#pragma warning(disable : 4786)
|
// with pragma push/pop).
|
||||||
#endif // if defined(_MSC_VER) && _MSC_VER < 1200 // MSVC 6
|
# pragma warning(disable : 4786)
|
||||||
|
# endif // MSVC 6
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1500 // MSVC 2008
|
# if _MSC_VER >= 1500 // MSVC 2008
|
||||||
/// Indicates that the following function is deprecated.
|
/// Indicates that the following function is deprecated.
|
||||||
#define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
# define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // defined(_MSC_VER)
|
||||||
|
|
||||||
|
// In c++11 the override keyword allows you to explicity define that a function
|
||||||
|
// is intended to override the base-class version. This makes the code more
|
||||||
|
// managable and fixes a set of common hard-to-find bugs.
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER > 1600 && _MSC_VER < 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
|
#elif defined(_MSC_VER) && _MSC_VER >= 1900
|
||||||
|
# define JSONCPP_OVERRIDE override
|
||||||
|
# define JSONCPP_NOEXCEPT noexcept
|
||||||
|
#else
|
||||||
|
# define JSONCPP_OVERRIDE
|
||||||
|
# define JSONCPP_NOEXCEPT throw()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // MSVC >= 2010
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#if __has_feature(cxx_rvalue_references)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // has_feature
|
||||||
|
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 1
|
||||||
|
#endif // GXX_EXPERIMENTAL
|
||||||
|
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
|
#endif // not defined JSON_HAS_RVALUE_REFERENCES
|
||||||
|
|
||||||
|
#ifndef JSON_HAS_RVALUE_REFERENCES
|
||||||
|
#define JSON_HAS_RVALUE_REFERENCES 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
|
||||||
|
# if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__ ((deprecated(message)))
|
||||||
|
# elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
|
||||||
|
# define JSONCPP_DEPRECATED(message) __attribute__((__deprecated__))
|
||||||
|
# endif // GNUC version
|
||||||
|
#endif // __clang__ || __GNUC__
|
||||||
|
|
||||||
#if !defined(JSONCPP_DEPRECATED)
|
#if !defined(JSONCPP_DEPRECATED)
|
||||||
#define JSONCPP_DEPRECATED(message)
|
#define JSONCPP_DEPRECATED(message)
|
||||||
#endif // if !defined(JSONCPP_DEPRECATED)
|
#endif // if !defined(JSONCPP_DEPRECATED)
|
||||||
|
|
||||||
|
#if __GNUC__ >= 6
|
||||||
|
# define JSON_USE_INT64_DOUBLE_CONVERSION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
# include "version.h"
|
||||||
|
|
||||||
|
# if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
# include "allocator.h" //typedef Allocator
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
typedef int Int;
|
typedef int Int;
|
||||||
typedef unsigned int UInt;
|
typedef unsigned int UInt;
|
||||||
@@ -89,13 +159,26 @@ typedef unsigned int LargestUInt;
|
|||||||
typedef __int64 Int64;
|
typedef __int64 Int64;
|
||||||
typedef unsigned __int64 UInt64;
|
typedef unsigned __int64 UInt64;
|
||||||
#else // if defined(_MSC_VER) // Other platforms, use long long
|
#else // if defined(_MSC_VER) // Other platforms, use long long
|
||||||
typedef long long int Int64;
|
typedef int64_t Int64;
|
||||||
typedef unsigned long long int UInt64;
|
typedef uint64_t UInt64;
|
||||||
#endif // if defined(_MSC_VER)
|
#endif // if defined(_MSC_VER)
|
||||||
typedef Int64 LargestInt;
|
typedef Int64 LargestInt;
|
||||||
typedef UInt64 LargestUInt;
|
typedef UInt64 LargestUInt;
|
||||||
#define JSON_HAS_INT64
|
#define JSON_HAS_INT64
|
||||||
#endif // if defined(JSON_NO_INT64)
|
#endif // if defined(JSON_NO_INT64)
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#define JSONCPP_STRING std::basic_string<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::basic_ostringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_OSTREAM std::basic_ostream<char, std::char_traits<char>>
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::basic_istringstream<char, std::char_traits<char>, Json::SecureAllocator<char> >
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#else
|
||||||
|
#define JSONCPP_STRING std::string
|
||||||
|
#define JSONCPP_OSTRINGSTREAM std::ostringstream
|
||||||
|
#define JSONCPP_OSTREAM std::ostream
|
||||||
|
#define JSONCPP_ISTRINGSTREAM std::istringstream
|
||||||
|
#define JSONCPP_ISTREAM std::istream
|
||||||
|
#endif // if JSONCPP_USING_SECURE_MEMORY
|
||||||
} // end namespace Json
|
} // end namespace Json
|
||||||
|
|
||||||
#endif // JSON_CONFIG_H_INCLUDED
|
#endif // JSON_CONFIG_H_INCLUDED
|
||||||
|
@@ -10,6 +10,8 @@
|
|||||||
#include "forwards.h"
|
#include "forwards.h"
|
||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
|
|
||||||
|
#pragma pack(push, 8)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Configuration passed to reader and writer.
|
/** \brief Configuration passed to reader and writer.
|
||||||
@@ -54,4 +56,6 @@ public:
|
|||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
#endif // CPPTL_JSON_FEATURES_H_INCLUDED
|
||||||
|
@@ -23,6 +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)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
|
||||||
@@ -42,9 +44,9 @@ public:
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct StructuredError {
|
struct StructuredError {
|
||||||
size_t offset_start;
|
ptrdiff_t offset_start;
|
||||||
size_t offset_limit;
|
ptrdiff_t offset_limit;
|
||||||
std::string message;
|
JSONCPP_STRING message;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Constructs a Reader allowing all features
|
/** \brief Constructs a Reader allowing all features
|
||||||
@@ -99,7 +101,7 @@ public:
|
|||||||
|
|
||||||
/// \brief Parse from input stream.
|
/// \brief Parse from input stream.
|
||||||
/// \see Json::operator>>(std::istream&, Json::Value&).
|
/// \see Json::operator>>(std::istream&, Json::Value&).
|
||||||
bool parse(std::istream& is, Value& root, bool collectComments = true);
|
bool parse(JSONCPP_ISTREAM& is, Value& root, bool collectComments = true);
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
* document.
|
* document.
|
||||||
@@ -110,8 +112,8 @@ public:
|
|||||||
* during parsing.
|
* during parsing.
|
||||||
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
* \deprecated Use getFormattedErrorMessages() instead (typo fix).
|
||||||
*/
|
*/
|
||||||
JSONCPP_DEPRECATED("Use getFormattedErrorMessages instead")
|
JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
|
||||||
std::string getFormatedErrorMessages() const;
|
JSONCPP_STRING getFormatedErrorMessages() const;
|
||||||
|
|
||||||
/** \brief Returns a user friendly string that list errors in the parsed
|
/** \brief Returns a user friendly string that list errors in the parsed
|
||||||
* document.
|
* document.
|
||||||
@@ -121,7 +123,7 @@ public:
|
|||||||
* occurred
|
* occurred
|
||||||
* during parsing.
|
* during parsing.
|
||||||
*/
|
*/
|
||||||
std::string getFormattedErrorMessages() const;
|
JSONCPP_STRING getFormattedErrorMessages() const;
|
||||||
|
|
||||||
/** \brief Returns a vector of structured erros encounted while parsing.
|
/** \brief Returns a vector of structured erros encounted while parsing.
|
||||||
* \return A (possibly empty) vector of StructuredError objects. Currently
|
* \return A (possibly empty) vector of StructuredError objects. Currently
|
||||||
@@ -138,7 +140,7 @@ public:
|
|||||||
* \return \c true if the error was successfully added, \c false if the
|
* \return \c true if the error was successfully added, \c false if the
|
||||||
* Value offset exceeds the document size.
|
* Value offset exceeds the document size.
|
||||||
*/
|
*/
|
||||||
bool pushError(const Value& value, const std::string& message);
|
bool pushError(const Value& value, const JSONCPP_STRING& message);
|
||||||
|
|
||||||
/** \brief Add a semantic error message with extra context.
|
/** \brief Add a semantic error message with extra context.
|
||||||
* \param value JSON Value location associated with the error
|
* \param value JSON Value location associated with the error
|
||||||
@@ -147,7 +149,7 @@ public:
|
|||||||
* \return \c true if the error was successfully added, \c false if either
|
* \return \c true if the error was successfully added, \c false if either
|
||||||
* Value offset exceeds the document size.
|
* Value offset exceeds the document size.
|
||||||
*/
|
*/
|
||||||
bool pushError(const Value& value, const std::string& message, const Value& extra);
|
bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
|
||||||
|
|
||||||
/** \brief Return whether there are any errors.
|
/** \brief Return whether there are any errors.
|
||||||
* \return \c true if there are no errors to report \c false if
|
* \return \c true if there are no errors to report \c false if
|
||||||
@@ -183,7 +185,7 @@ private:
|
|||||||
class ErrorInfo {
|
class ErrorInfo {
|
||||||
public:
|
public:
|
||||||
Token token_;
|
Token token_;
|
||||||
std::string message_;
|
JSONCPP_STRING message_;
|
||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -203,7 +205,7 @@ private:
|
|||||||
bool decodeNumber(Token& token);
|
bool decodeNumber(Token& token);
|
||||||
bool decodeNumber(Token& token, Value& decoded);
|
bool decodeNumber(Token& token, Value& decoded);
|
||||||
bool decodeString(Token& token);
|
bool decodeString(Token& token);
|
||||||
bool decodeString(Token& token, std::string& decoded);
|
bool decodeString(Token& token, JSONCPP_STRING& decoded);
|
||||||
bool decodeDouble(Token& token);
|
bool decodeDouble(Token& token);
|
||||||
bool decodeDouble(Token& token, Value& decoded);
|
bool decodeDouble(Token& token, Value& decoded);
|
||||||
bool decodeUnicodeCodePoint(Token& token,
|
bool decodeUnicodeCodePoint(Token& token,
|
||||||
@@ -214,9 +216,9 @@ private:
|
|||||||
Location& current,
|
Location& current,
|
||||||
Location end,
|
Location end,
|
||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool addError(const std::string& message, Token& token, Location extra = 0);
|
bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const std::string& message,
|
bool addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
Token& token,
|
Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
void skipUntilSpace();
|
void skipUntilSpace();
|
||||||
@@ -224,20 +226,20 @@ private:
|
|||||||
Char getNextChar();
|
Char getNextChar();
|
||||||
void
|
void
|
||||||
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
||||||
std::string getLocationLineAndColumn(Location location) const;
|
JSONCPP_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);
|
void skipCommentTokens(Token& token);
|
||||||
|
|
||||||
typedef std::stack<Value*> Nodes;
|
typedef std::stack<Value*> Nodes;
|
||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
Location begin_;
|
Location begin_;
|
||||||
Location end_;
|
Location end_;
|
||||||
Location current_;
|
Location current_;
|
||||||
Location lastValueEnd_;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_;
|
Value* lastValue_;
|
||||||
std::string commentsBefore_;
|
JSONCPP_STRING commentsBefore_;
|
||||||
Features features_;
|
Features features_;
|
||||||
bool collectComments_;
|
bool collectComments_;
|
||||||
}; // Reader
|
}; // Reader
|
||||||
@@ -266,10 +268,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool parse(
|
virtual bool parse(
|
||||||
char const* beginDoc, char const* endDoc,
|
char const* beginDoc, char const* endDoc,
|
||||||
Value* root, std::string* errs) = 0;
|
Value* root, JSONCPP_STRING* errs) = 0;
|
||||||
|
|
||||||
class Factory {
|
class JSON_API Factory {
|
||||||
public:
|
public:
|
||||||
|
virtual ~Factory() {}
|
||||||
/** \brief Allocate a CharReader via operator new().
|
/** \brief Allocate a CharReader via operator new().
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
@@ -279,15 +282,13 @@ public:
|
|||||||
|
|
||||||
/** \brief Build a CharReader implementation.
|
/** \brief Build a CharReader implementation.
|
||||||
|
|
||||||
\deprecated This is experimental and will be altered before the next release.
|
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
\code
|
\code
|
||||||
using namespace Json;
|
using namespace Json;
|
||||||
CharReaderBuilder builder;
|
CharReaderBuilder builder;
|
||||||
builder["collectComments"] = false;
|
builder["collectComments"] = false;
|
||||||
Value value;
|
Value value;
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
bool ok = parseFromStream(builder, std::cin, &value, &errs);
|
||||||
\endcode
|
\endcode
|
||||||
*/
|
*/
|
||||||
@@ -322,6 +323,9 @@ public:
|
|||||||
the JSON value in the input string.
|
the JSON value in the input string.
|
||||||
- `"rejectDupKeys": false or true`
|
- `"rejectDupKeys": false or true`
|
||||||
- If true, `parse()` returns false when a key is duplicated within an object.
|
- If true, `parse()` returns false when a key is duplicated within an object.
|
||||||
|
- `"allowSpecialFloats": false or true`
|
||||||
|
- If true, special float values (NaNs and infinities) are allowed
|
||||||
|
and their values are lossfree restorable.
|
||||||
|
|
||||||
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
|
||||||
@@ -331,9 +335,9 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
CharReaderBuilder();
|
CharReaderBuilder();
|
||||||
virtual ~CharReaderBuilder();
|
~CharReaderBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
virtual CharReader* newCharReader() const;
|
CharReader* newCharReader() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
@@ -342,18 +346,18 @@ public:
|
|||||||
|
|
||||||
/** A simple way to update a specific setting.
|
/** A simple way to update a specific setting.
|
||||||
*/
|
*/
|
||||||
Value& operator[](std::string key);
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
/** Called by ctor, but you can use this to reset settings_.
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
* \pre 'settings' != NULL (but Json::null is fine)
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
* \remark Defaults:
|
* \remark Defaults:
|
||||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
||||||
*/
|
*/
|
||||||
static void setDefaults(Json::Value* settings);
|
static void setDefaults(Json::Value* settings);
|
||||||
/** Same as old Features::strictMode().
|
/** Same as old Features::strictMode().
|
||||||
* \pre 'settings' != NULL (but Json::null is fine)
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
* \remark Defaults:
|
* \remark Defaults:
|
||||||
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
|
* \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
|
||||||
*/
|
*/
|
||||||
static void strictMode(Json::Value* settings);
|
static void strictMode(Json::Value* settings);
|
||||||
};
|
};
|
||||||
@@ -364,7 +368,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool JSON_API parseFromStream(
|
bool JSON_API parseFromStream(
|
||||||
CharReader::Factory const&,
|
CharReader::Factory const&,
|
||||||
std::istream&,
|
JSONCPP_ISTREAM&,
|
||||||
Value* root, std::string* errs);
|
Value* root, std::string* errs);
|
||||||
|
|
||||||
/** \brief Read from 'sin' into 'root'.
|
/** \brief Read from 'sin' into 'root'.
|
||||||
@@ -391,10 +395,12 @@ bool JSON_API parseFromStream(
|
|||||||
\throw std::exception on parse error.
|
\throw std::exception on parse error.
|
||||||
\see Json::operator<<()
|
\see Json::operator<<()
|
||||||
*/
|
*/
|
||||||
JSON_API std::istream& operator>>(std::istream&, Value&);
|
JSON_API JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM&, Value&);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
@@ -11,6 +11,7 @@
|
|||||||
#endif // if !defined(JSON_IS_AMALGAMATION)
|
#endif // if !defined(JSON_IS_AMALGAMATION)
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#ifndef JSON_USE_CPPTL_SMALLMAP
|
#ifndef JSON_USE_CPPTL_SMALLMAP
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -21,6 +22,19 @@
|
|||||||
#include <cpptl/forwards.h>
|
#include <cpptl/forwards.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//Conditional NORETURN attribute on the throw functions would:
|
||||||
|
// a) suppress false positives from static code analysis
|
||||||
|
// b) possibly improve optimization opportunities.
|
||||||
|
#if !defined(JSONCPP_NORETURN)
|
||||||
|
# if defined(_MSC_VER)
|
||||||
|
# define JSONCPP_NORETURN __declspec(noreturn)
|
||||||
|
# elif defined(__GNUC__)
|
||||||
|
# define JSONCPP_NORETURN __attribute__ ((__noreturn__))
|
||||||
|
# else
|
||||||
|
# define JSONCPP_NORETURN
|
||||||
|
# endif
|
||||||
|
#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)
|
||||||
@@ -28,10 +42,52 @@
|
|||||||
#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)
|
||||||
|
|
||||||
/** \brief JSON (JavaScript Object Notation).
|
/** \brief JSON (JavaScript Object Notation).
|
||||||
*/
|
*/
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
|
/** Base class for all exceptions we throw.
|
||||||
|
*
|
||||||
|
* We use nothing but these internally. Of course, STL can throw others.
|
||||||
|
*/
|
||||||
|
class JSON_API Exception : public std::exception {
|
||||||
|
public:
|
||||||
|
Exception(JSONCPP_STRING const& msg);
|
||||||
|
~Exception() JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
char const* what() const JSONCPP_NOEXCEPT JSONCPP_OVERRIDE;
|
||||||
|
protected:
|
||||||
|
JSONCPP_STRING msg_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions which the user cannot easily avoid.
|
||||||
|
*
|
||||||
|
* E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API RuntimeError : public Exception {
|
||||||
|
public:
|
||||||
|
RuntimeError(JSONCPP_STRING const& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
|
||||||
|
*
|
||||||
|
* These are precondition-violations (user bugs) and internal errors (our bugs).
|
||||||
|
*
|
||||||
|
* \remark derived from Json::Exception
|
||||||
|
*/
|
||||||
|
class JSON_API LogicError : public Exception {
|
||||||
|
public:
|
||||||
|
LogicError(JSONCPP_STRING const& msg);
|
||||||
|
};
|
||||||
|
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg);
|
||||||
|
/// used internally
|
||||||
|
JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg);
|
||||||
|
|
||||||
/** \brief Type of the value held by a Value object.
|
/** \brief Type of the value held by a Value object.
|
||||||
*/
|
*/
|
||||||
enum ValueType {
|
enum ValueType {
|
||||||
@@ -121,7 +177,7 @@ private:
|
|||||||
class JSON_API Value {
|
class JSON_API Value {
|
||||||
friend class ValueIteratorBase;
|
friend class ValueIteratorBase;
|
||||||
public:
|
public:
|
||||||
typedef std::vector<std::string> Members;
|
typedef std::vector<JSONCPP_STRING> Members;
|
||||||
typedef ValueIterator iterator;
|
typedef ValueIterator iterator;
|
||||||
typedef ValueConstIterator const_iterator;
|
typedef ValueConstIterator const_iterator;
|
||||||
typedef Json::UInt UInt;
|
typedef Json::UInt UInt;
|
||||||
@@ -136,6 +192,8 @@ public:
|
|||||||
|
|
||||||
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
static const Value& null; ///< We regret this reference to a global instance; prefer the simpler Value().
|
||||||
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
static const Value& nullRef; ///< just a kludge for binary-compatibility; same as null
|
||||||
|
static Value const& nullSingleton(); ///< Prefer this to null or nullRef.
|
||||||
|
|
||||||
/// Minimum signed integer value that can be stored in a Json::Value.
|
/// Minimum signed integer value that can be stored in a Json::Value.
|
||||||
static const LargestInt minLargestInt;
|
static const LargestInt minLargestInt;
|
||||||
/// Maximum signed integer value that can be stored in a Json::Value.
|
/// Maximum signed integer value that can be stored in a Json::Value.
|
||||||
@@ -171,6 +229,9 @@ private:
|
|||||||
CZString(ArrayIndex index);
|
CZString(ArrayIndex index);
|
||||||
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
CZString(char const* str, unsigned length, DuplicationPolicy allocate);
|
||||||
CZString(CZString const& other);
|
CZString(CZString const& other);
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
CZString(CZString&& other);
|
||||||
|
#endif
|
||||||
~CZString();
|
~CZString();
|
||||||
CZString& operator=(CZString other);
|
CZString& operator=(CZString other);
|
||||||
bool operator<(CZString const& other) const;
|
bool operator<(CZString const& other) const;
|
||||||
@@ -185,7 +246,7 @@ private:
|
|||||||
void swap(CZString& other);
|
void swap(CZString& other);
|
||||||
|
|
||||||
struct StringStorage {
|
struct StringStorage {
|
||||||
DuplicationPolicy policy_: 2;
|
unsigned policy_: 2;
|
||||||
unsigned length_: 30; // 1GB max
|
unsigned length_: 30; // 1GB max
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -229,7 +290,7 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
#endif // if defined(JSON_HAS_INT64)
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
Value(double value);
|
Value(double value);
|
||||||
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
|
Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
|
||||||
Value(const char* beginValue, const char* endValue); ///< Copy all, incl zeroes.
|
Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
|
||||||
/** \brief Constructs a value from a static string.
|
/** \brief Constructs a value from a static string.
|
||||||
|
|
||||||
* Like other value string constructor but do not duplicate the string for
|
* Like other value string constructor but do not duplicate the string for
|
||||||
@@ -246,13 +307,17 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
* \endcode
|
* \endcode
|
||||||
*/
|
*/
|
||||||
Value(const StaticString& value);
|
Value(const StaticString& value);
|
||||||
Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too.
|
Value(const JSONCPP_STRING& value); ///< Copy data() til size(). Embedded zeroes too.
|
||||||
#ifdef JSON_USE_CPPTL
|
#ifdef JSON_USE_CPPTL
|
||||||
Value(const CppTL::ConstString& value);
|
Value(const CppTL::ConstString& value);
|
||||||
#endif
|
#endif
|
||||||
Value(bool value);
|
Value(bool value);
|
||||||
/// Deep copy.
|
/// Deep copy.
|
||||||
Value(const Value& other);
|
Value(const Value& other);
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
/// Move constructor
|
||||||
|
Value(Value&& other);
|
||||||
|
#endif
|
||||||
~Value();
|
~Value();
|
||||||
|
|
||||||
/// Deep copy, then swap(other).
|
/// Deep copy, then swap(other).
|
||||||
@@ -275,12 +340,15 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
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!
|
||||||
std::string asString() const; ///< Embedded zeroes are possible.
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
unsigned getCStringLength() const; //Allows you to understand the length of the CString
|
||||||
|
#endif
|
||||||
|
JSONCPP_STRING asString() const; ///< Embedded zeroes are possible.
|
||||||
/** Get raw char* of string-value.
|
/** Get raw char* of string-value.
|
||||||
* \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(
|
bool getString(
|
||||||
char const** str, char const** end) const;
|
char const** begin, char const** end) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
#ifdef JSON_USE_CPPTL
|
||||||
CppTL::ConstString asConstString() const;
|
CppTL::ConstString asConstString() const;
|
||||||
#endif
|
#endif
|
||||||
@@ -379,11 +447,11 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
const Value& operator[](const char* key) const;
|
const Value& operator[](const char* key) const;
|
||||||
/// 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.
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
Value& operator[](const std::string& key);
|
Value& operator[](const JSONCPP_STRING& key);
|
||||||
/// Access an object value by name, returns null if there is no member with
|
/// Access an object value by name, returns null if there is no member with
|
||||||
/// that name.
|
/// that name.
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
const Value& operator[](const std::string& key) const;
|
const Value& operator[](const JSONCPP_STRING& key) const;
|
||||||
/** \brief Access an object value by name, create a null member if it does not
|
/** \brief Access an object value by name, create a null member if it does not
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
@@ -409,12 +477,12 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
Value get(const char* key, const Value& defaultValue) const;
|
Value get(const char* key, const Value& defaultValue) const;
|
||||||
/// 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
|
||||||
/// \param key may contain embedded nulls.
|
/// \note key may contain embedded nulls.
|
||||||
Value get(const char* key, const char* end, const Value& defaultValue) const;
|
Value get(const char* begin, const char* end, const Value& defaultValue) const;
|
||||||
/// 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
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
Value get(const std::string& key, const Value& defaultValue) const;
|
Value get(const JSONCPP_STRING& key, const Value& defaultValue) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
#ifdef JSON_USE_CPPTL
|
||||||
/// 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
|
||||||
@@ -422,12 +490,12 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
#endif
|
#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-key) >= 2^30
|
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
|
||||||
Value const* find(char const* key, char const* end) const;
|
Value const* find(char const* begin, char const* end) 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-key) >= 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.
|
||||||
Value const* demand(char const* key, char const* end);
|
Value const* demand(char const* begin, char const* end);
|
||||||
/// \brief Remove and return the named member.
|
/// \brief Remove and return the named member.
|
||||||
///
|
///
|
||||||
/// Do nothing if it did not exist.
|
/// Do nothing if it did not exist.
|
||||||
@@ -439,8 +507,8 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
/// Same as removeMember(const char*)
|
/// Same as removeMember(const char*)
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
/// \deprecated
|
/// \deprecated
|
||||||
Value removeMember(const std::string& key);
|
Value removeMember(const JSONCPP_STRING& key);
|
||||||
/// Same as removeMember(const char* key, const char* end, Value* removed),
|
/// Same as removeMember(const char* begin, const char* end, Value* removed),
|
||||||
/// but 'key' is null-terminated.
|
/// but 'key' is null-terminated.
|
||||||
bool removeMember(const char* key, Value* removed);
|
bool removeMember(const char* key, Value* removed);
|
||||||
/** \brief Remove the named map member.
|
/** \brief Remove the named map member.
|
||||||
@@ -449,9 +517,9 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
\param key may contain embedded nulls.
|
\param key may contain embedded nulls.
|
||||||
\return true iff removed (no exceptions)
|
\return true iff removed (no exceptions)
|
||||||
*/
|
*/
|
||||||
bool removeMember(std::string const& key, Value* removed);
|
bool removeMember(JSONCPP_STRING const& key, Value* removed);
|
||||||
/// Same as removeMember(std::string const& key, Value* removed)
|
/// Same as removeMember(JSONCPP_STRING const& key, Value* removed)
|
||||||
bool removeMember(const char* key, const char* end, Value* removed);
|
bool removeMember(const char* begin, const char* end, Value* removed);
|
||||||
/** \brief Remove the indexed array element.
|
/** \brief Remove the indexed array element.
|
||||||
|
|
||||||
O(n) expensive operations.
|
O(n) expensive operations.
|
||||||
@@ -465,9 +533,9 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
bool isMember(const char* key) const;
|
bool isMember(const char* key) const;
|
||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
/// \param key may contain embedded nulls.
|
/// \param key may contain embedded nulls.
|
||||||
bool isMember(const std::string& key) const;
|
bool isMember(const JSONCPP_STRING& key) const;
|
||||||
/// Same as isMember(std::string const& key)const
|
/// Same as isMember(JSONCPP_STRING const& key)const
|
||||||
bool isMember(const char* key, const char* end) const;
|
bool isMember(const char* begin, const char* end) const;
|
||||||
#ifdef JSON_USE_CPPTL
|
#ifdef JSON_USE_CPPTL
|
||||||
/// Return true if the object has a member named key.
|
/// Return true if the object has a member named key.
|
||||||
bool isMember(const CppTL::ConstString& key) const;
|
bool isMember(const CppTL::ConstString& key) const;
|
||||||
@@ -486,16 +554,17 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
//# endif
|
//# endif
|
||||||
|
|
||||||
/// \deprecated Always pass len.
|
/// \deprecated Always pass len.
|
||||||
|
JSONCPP_DEPRECATED("Use setComment(JSONCPP_STRING const&) instead.")
|
||||||
void setComment(const char* comment, CommentPlacement placement);
|
void setComment(const char* comment, CommentPlacement placement);
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
void setComment(const char* comment, size_t len, CommentPlacement placement);
|
||||||
/// Comments must be //... or /* ... */
|
/// Comments must be //... or /* ... */
|
||||||
void setComment(const std::string& comment, CommentPlacement placement);
|
void setComment(const JSONCPP_STRING& comment, CommentPlacement placement);
|
||||||
bool hasComment(CommentPlacement placement) const;
|
bool hasComment(CommentPlacement placement) const;
|
||||||
/// Include delimiters and embedded newlines.
|
/// Include delimiters and embedded newlines.
|
||||||
std::string getComment(CommentPlacement placement) const;
|
JSONCPP_STRING getComment(CommentPlacement placement) const;
|
||||||
|
|
||||||
std::string toStyledString() const;
|
JSONCPP_STRING toStyledString() const;
|
||||||
|
|
||||||
const_iterator begin() const;
|
const_iterator begin() const;
|
||||||
const_iterator end() const;
|
const_iterator end() const;
|
||||||
@@ -505,10 +574,10 @@ Json::Value obj_value(Json::objectValue); // {}
|
|||||||
|
|
||||||
// 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(size_t start);
|
void setOffsetStart(ptrdiff_t start);
|
||||||
void setOffsetLimit(size_t limit);
|
void setOffsetLimit(ptrdiff_t limit);
|
||||||
size_t getOffsetStart() const;
|
ptrdiff_t getOffsetStart() const;
|
||||||
size_t getOffsetLimit() const;
|
ptrdiff_t getOffsetLimit() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void initBasic(ValueType type, bool allocated = false);
|
void initBasic(ValueType type, bool allocated = false);
|
||||||
@@ -549,8 +618,8 @@ private:
|
|||||||
|
|
||||||
// [start, limit) byte offsets in the source JSON text from which this Value
|
// [start, limit) byte offsets in the source JSON text from which this Value
|
||||||
// was extracted.
|
// was extracted.
|
||||||
size_t start_;
|
ptrdiff_t start_;
|
||||||
size_t limit_;
|
ptrdiff_t limit_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Experimental and untested: represents an element of the "path" to
|
/** \brief Experimental and untested: represents an element of the "path" to
|
||||||
@@ -563,7 +632,7 @@ public:
|
|||||||
PathArgument();
|
PathArgument();
|
||||||
PathArgument(ArrayIndex index);
|
PathArgument(ArrayIndex index);
|
||||||
PathArgument(const char* key);
|
PathArgument(const char* key);
|
||||||
PathArgument(const std::string& key);
|
PathArgument(const JSONCPP_STRING& key);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Kind {
|
enum Kind {
|
||||||
@@ -571,7 +640,7 @@ private:
|
|||||||
kindIndex,
|
kindIndex,
|
||||||
kindKey
|
kindKey
|
||||||
};
|
};
|
||||||
std::string key_;
|
JSONCPP_STRING key_;
|
||||||
ArrayIndex index_;
|
ArrayIndex index_;
|
||||||
Kind kind_;
|
Kind kind_;
|
||||||
};
|
};
|
||||||
@@ -589,7 +658,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API Path {
|
class JSON_API Path {
|
||||||
public:
|
public:
|
||||||
Path(const std::string& path,
|
Path(const JSONCPP_STRING& path,
|
||||||
const PathArgument& a1 = PathArgument(),
|
const PathArgument& a1 = PathArgument(),
|
||||||
const PathArgument& a2 = PathArgument(),
|
const PathArgument& a2 = PathArgument(),
|
||||||
const PathArgument& a3 = PathArgument(),
|
const PathArgument& a3 = PathArgument(),
|
||||||
@@ -606,12 +675,12 @@ private:
|
|||||||
typedef std::vector<const PathArgument*> InArgs;
|
typedef std::vector<const PathArgument*> InArgs;
|
||||||
typedef std::vector<PathArgument> Args;
|
typedef std::vector<PathArgument> Args;
|
||||||
|
|
||||||
void makePath(const std::string& path, const InArgs& in);
|
void makePath(const JSONCPP_STRING& path, const InArgs& in);
|
||||||
void addPathInArg(const std::string& path,
|
void addPathInArg(const JSONCPP_STRING& path,
|
||||||
const InArgs& in,
|
const InArgs& in,
|
||||||
InArgs::const_iterator& itInArg,
|
InArgs::const_iterator& itInArg,
|
||||||
PathArgument::Kind kind);
|
PathArgument::Kind kind);
|
||||||
void invalidPath(const std::string& path, int location);
|
void invalidPath(const JSONCPP_STRING& path, int location);
|
||||||
|
|
||||||
Args args_;
|
Args args_;
|
||||||
};
|
};
|
||||||
@@ -626,9 +695,6 @@ public:
|
|||||||
typedef int difference_type;
|
typedef int difference_type;
|
||||||
typedef ValueIteratorBase SelfType;
|
typedef ValueIteratorBase SelfType;
|
||||||
|
|
||||||
ValueIteratorBase();
|
|
||||||
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
|
||||||
|
|
||||||
bool operator==(const SelfType& other) const { return isEqual(other); }
|
bool operator==(const SelfType& other) const { return isEqual(other); }
|
||||||
|
|
||||||
bool operator!=(const SelfType& other) const { return !isEqual(other); }
|
bool operator!=(const SelfType& other) const { return !isEqual(other); }
|
||||||
@@ -641,16 +707,22 @@ public:
|
|||||||
/// Value.
|
/// Value.
|
||||||
Value key() const;
|
Value key() const;
|
||||||
|
|
||||||
/// Return the index of the referenced Value. -1 if it is not an arrayValue.
|
/// Return the index of the referenced Value, or -1 if it is not an arrayValue.
|
||||||
UInt index() const;
|
UInt index() const;
|
||||||
|
|
||||||
|
/// Return the member name of the referenced Value, or "" if it is not an
|
||||||
|
/// objectValue.
|
||||||
|
/// \note Avoid `c_str()` on result, as embedded zeroes are possible.
|
||||||
|
JSONCPP_STRING name() const;
|
||||||
|
|
||||||
/// Return the member name of the referenced Value. "" if it is not an
|
/// Return the member name of the referenced Value. "" if it is not an
|
||||||
/// objectValue.
|
/// objectValue.
|
||||||
/// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
|
/// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
|
||||||
|
JSONCPP_DEPRECATED("Use `key = name();` instead.")
|
||||||
char const* memberName() const;
|
char const* memberName() const;
|
||||||
/// Return the member name of the referenced Value, or NULL if it is not an
|
/// Return the member name of the referenced Value, or NULL if it is not an
|
||||||
/// objectValue.
|
/// objectValue.
|
||||||
/// Better version than memberName(). Allows embedded nulls.
|
/// \note Better version than memberName(). Allows embedded nulls.
|
||||||
char const* memberName(char const** end) const;
|
char const* memberName(char const** end) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -670,6 +742,12 @@ private:
|
|||||||
Value::ObjectValues::iterator current_;
|
Value::ObjectValues::iterator current_;
|
||||||
// Indicates that iterator is for a null value.
|
// Indicates that iterator is for a null value.
|
||||||
bool isNull_;
|
bool isNull_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
// For some reason, BORLAND needs these at the end, rather
|
||||||
|
// than earlier. No idea why.
|
||||||
|
ValueIteratorBase();
|
||||||
|
explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief const iterator for object and array value.
|
/** \brief const iterator for object and array value.
|
||||||
@@ -687,6 +765,7 @@ public:
|
|||||||
typedef ValueConstIterator SelfType;
|
typedef ValueConstIterator SelfType;
|
||||||
|
|
||||||
ValueConstIterator();
|
ValueConstIterator();
|
||||||
|
ValueConstIterator(ValueIterator const& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*! \internal Use by Value to create an iterator.
|
/*! \internal Use by Value to create an iterator.
|
||||||
@@ -736,7 +815,7 @@ public:
|
|||||||
typedef ValueIterator SelfType;
|
typedef ValueIterator SelfType;
|
||||||
|
|
||||||
ValueIterator();
|
ValueIterator();
|
||||||
ValueIterator(const ValueConstIterator& other);
|
explicit ValueIterator(const ValueConstIterator& other);
|
||||||
ValueIterator(const ValueIterator& other);
|
ValueIterator(const ValueIterator& other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -782,6 +861,7 @@ template<>
|
|||||||
inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
|
inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
@@ -1,14 +1,20 @@
|
|||||||
// DO NOT EDIT. This file is generated by CMake from "version"
|
// DO NOT EDIT. This file (and "version") is generated by CMake.
|
||||||
// and "version.h.in" files.
|
|
||||||
// Run CMake configure step to update it.
|
// Run CMake configure step to update it.
|
||||||
#ifndef JSON_VERSION_H_INCLUDED
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
# define JSON_VERSION_H_INCLUDED
|
# define JSON_VERSION_H_INCLUDED
|
||||||
|
|
||||||
# define JSONCPP_VERSION_STRING "1.5.4"
|
# define JSONCPP_VERSION_STRING "1.8.1"
|
||||||
# define JSONCPP_VERSION_MAJOR 1
|
# define JSONCPP_VERSION_MAJOR 1
|
||||||
# define JSONCPP_VERSION_MINOR 5
|
# define JSONCPP_VERSION_MINOR 8
|
||||||
# define JSONCPP_VERSION_PATCH 4
|
# define JSONCPP_VERSION_PATCH 1
|
||||||
# define JSONCPP_VERSION_QUALIFIER
|
# define JSONCPP_VERSION_QUALIFIER
|
||||||
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY 0
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
#endif // JSON_VERSION_H_INCLUDED
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
|
@@ -20,6 +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)
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
class Value;
|
class Value;
|
||||||
@@ -39,17 +41,17 @@ Usage:
|
|||||||
*/
|
*/
|
||||||
class JSON_API StreamWriter {
|
class JSON_API StreamWriter {
|
||||||
protected:
|
protected:
|
||||||
std::ostream* sout_; // not owned; will not delete
|
JSONCPP_OSTREAM* sout_; // not owned; will not delete
|
||||||
public:
|
public:
|
||||||
StreamWriter();
|
StreamWriter();
|
||||||
virtual ~StreamWriter();
|
virtual ~StreamWriter();
|
||||||
/** Write Value into document as configured in sub-class.
|
/** Write Value into document as configured in sub-class.
|
||||||
Do not take ownership of sout, but maintain a reference during function.
|
Do not take ownership of sout, but maintain a reference during function.
|
||||||
\pre sout != NULL
|
\pre sout != NULL
|
||||||
\return zero on success
|
\return zero on success (For now, we always return zero, so check the stream instead.)
|
||||||
\throw std::exception possibly, depending on configuration
|
\throw std::exception possibly, depending on configuration
|
||||||
*/
|
*/
|
||||||
virtual int write(Value const& root, std::ostream* sout) = 0;
|
virtual int write(Value const& root, JSONCPP_OSTREAM* sout) = 0;
|
||||||
|
|
||||||
/** \brief A simple abstract factory.
|
/** \brief A simple abstract factory.
|
||||||
*/
|
*/
|
||||||
@@ -66,7 +68,7 @@ public:
|
|||||||
/** \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.
|
||||||
*/
|
*/
|
||||||
std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
|
JSONCPP_STRING JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
|
||||||
|
|
||||||
|
|
||||||
/** \brief Build a StreamWriter implementation.
|
/** \brief Build a StreamWriter implementation.
|
||||||
@@ -99,6 +101,10 @@ public:
|
|||||||
Strictly speaking, this is not valid JSON. But when the output is being
|
Strictly speaking, this is not valid JSON. But when the output is being
|
||||||
fed to a browser's Javascript, it makes for smaller output and the
|
fed to a browser's Javascript, it makes for smaller output and the
|
||||||
browser can handle the output just fine.
|
browser can handle the output just fine.
|
||||||
|
- "useSpecialFloats": false or true
|
||||||
|
- If true, outputs non-finite floating point values in the following way:
|
||||||
|
NaN values as "NaN", positive infinity as "Infinity", and negative infinity
|
||||||
|
as "-Infinity".
|
||||||
|
|
||||||
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
|
||||||
@@ -108,12 +114,12 @@ public:
|
|||||||
Json::Value settings_;
|
Json::Value settings_;
|
||||||
|
|
||||||
StreamWriterBuilder();
|
StreamWriterBuilder();
|
||||||
virtual ~StreamWriterBuilder();
|
~StreamWriterBuilder() JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
* \throw std::exception if something goes wrong (e.g. invalid settings)
|
||||||
*/
|
*/
|
||||||
virtual StreamWriter* newStreamWriter() const;
|
StreamWriter* newStreamWriter() const JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
/** \return true if 'settings' are legal and consistent;
|
/** \return true if 'settings' are legal and consistent;
|
||||||
* otherwise, indicate bad settings via 'invalid'.
|
* otherwise, indicate bad settings via 'invalid'.
|
||||||
@@ -121,7 +127,7 @@ public:
|
|||||||
bool validate(Json::Value* invalid) const;
|
bool validate(Json::Value* invalid) const;
|
||||||
/** A simple way to update a specific setting.
|
/** A simple way to update a specific setting.
|
||||||
*/
|
*/
|
||||||
Value& operator[](std::string key);
|
Value& operator[](JSONCPP_STRING key);
|
||||||
|
|
||||||
/** Called by ctor, but you can use this to reset settings_.
|
/** Called by ctor, but you can use this to reset settings_.
|
||||||
* \pre 'settings' != NULL (but Json::null is fine)
|
* \pre 'settings' != NULL (but Json::null is fine)
|
||||||
@@ -132,13 +138,13 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Abstract class for writers.
|
/** \brief Abstract class for writers.
|
||||||
* \deprecated Use StreamWriter.
|
* \deprecated Use StreamWriter. (And really, this is an implementation detail.)
|
||||||
*/
|
*/
|
||||||
class JSON_API Writer {
|
class JSON_API Writer {
|
||||||
public:
|
public:
|
||||||
virtual ~Writer();
|
virtual ~Writer();
|
||||||
|
|
||||||
virtual std::string write(const Value& root) = 0;
|
virtual JSONCPP_STRING write(const Value& root) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
|
||||||
@@ -151,9 +157,10 @@ public:
|
|||||||
* \deprecated Use StreamWriterBuilder.
|
* \deprecated Use StreamWriterBuilder.
|
||||||
*/
|
*/
|
||||||
class JSON_API FastWriter : public Writer {
|
class JSON_API FastWriter : public Writer {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FastWriter();
|
FastWriter();
|
||||||
virtual ~FastWriter() {}
|
~FastWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
void enableYAMLCompatibility();
|
void enableYAMLCompatibility();
|
||||||
|
|
||||||
@@ -167,12 +174,12 @@ public:
|
|||||||
void omitEndingLineFeed();
|
void omitEndingLineFeed();
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
virtual std::string write(const Value& root);
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
|
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
bool yamlCompatiblityEnabled_;
|
bool yamlCompatiblityEnabled_;
|
||||||
bool dropNullPlaceholders_;
|
bool dropNullPlaceholders_;
|
||||||
bool omitEndingLineFeed_;
|
bool omitEndingLineFeed_;
|
||||||
@@ -205,36 +212,36 @@ private:
|
|||||||
class JSON_API StyledWriter : public Writer {
|
class JSON_API StyledWriter : public Writer {
|
||||||
public:
|
public:
|
||||||
StyledWriter();
|
StyledWriter();
|
||||||
virtual ~StyledWriter() {}
|
~StyledWriter() JSONCPP_OVERRIDE {}
|
||||||
|
|
||||||
public: // overridden from Writer
|
public: // overridden from Writer
|
||||||
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
/** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
|
||||||
* \param root Value to serialize.
|
* \param root Value to serialize.
|
||||||
* \return String containing the JSON document that represents the root value.
|
* \return String containing the JSON document that represents the root value.
|
||||||
*/
|
*/
|
||||||
virtual std::string write(const Value& root);
|
JSONCPP_STRING write(const Value& root) JSONCPP_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
void writeArrayValue(const Value& value);
|
void writeArrayValue(const Value& value);
|
||||||
bool isMultineArray(const Value& value);
|
bool isMultineArray(const Value& value);
|
||||||
void pushValue(const std::string& value);
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent(const std::string& value);
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue(const Value& root);
|
void writeCommentBeforeValue(const Value& root);
|
||||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
bool hasCommentForValue(const Value& value);
|
bool hasCommentForValue(const Value& value);
|
||||||
static std::string normalizeEOL(const std::string& text);
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
std::string indentString_;
|
JSONCPP_STRING indentString_;
|
||||||
int rightMargin_;
|
unsigned int rightMargin_;
|
||||||
int indentSize_;
|
unsigned int indentSize_;
|
||||||
bool addChildValues_;
|
bool addChildValues_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -266,7 +273,7 @@ private:
|
|||||||
*/
|
*/
|
||||||
class JSON_API StyledStreamWriter {
|
class JSON_API StyledStreamWriter {
|
||||||
public:
|
public:
|
||||||
StyledStreamWriter(std::string indentation = "\t");
|
StyledStreamWriter(JSONCPP_STRING indentation = "\t");
|
||||||
~StyledStreamWriter() {}
|
~StyledStreamWriter() {}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -276,49 +283,51 @@ public:
|
|||||||
* \note There is no point in deriving from Writer, since write() should not
|
* \note There is no point in deriving from Writer, since write() should not
|
||||||
* return a value.
|
* return a value.
|
||||||
*/
|
*/
|
||||||
void write(std::ostream& out, const Value& root);
|
void write(JSONCPP_OSTREAM& out, const Value& root);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void writeValue(const Value& value);
|
void writeValue(const Value& value);
|
||||||
void writeArrayValue(const Value& value);
|
void writeArrayValue(const Value& value);
|
||||||
bool isMultineArray(const Value& value);
|
bool isMultineArray(const Value& value);
|
||||||
void pushValue(const std::string& value);
|
void pushValue(const JSONCPP_STRING& value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent(const std::string& value);
|
void writeWithIndent(const JSONCPP_STRING& value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue(const Value& root);
|
void writeCommentBeforeValue(const Value& root);
|
||||||
void writeCommentAfterValueOnSameLine(const Value& root);
|
void writeCommentAfterValueOnSameLine(const Value& root);
|
||||||
bool hasCommentForValue(const Value& value);
|
bool hasCommentForValue(const Value& value);
|
||||||
static std::string normalizeEOL(const std::string& text);
|
static JSONCPP_STRING normalizeEOL(const JSONCPP_STRING& text);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::ostream* document_;
|
JSONCPP_OSTREAM* document_;
|
||||||
std::string indentString_;
|
JSONCPP_STRING indentString_;
|
||||||
int rightMargin_;
|
unsigned int rightMargin_;
|
||||||
std::string indentation_;
|
JSONCPP_STRING indentation_;
|
||||||
bool addChildValues_ : 1;
|
bool addChildValues_ : 1;
|
||||||
bool indented_ : 1;
|
bool indented_ : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString(Int value);
|
JSONCPP_STRING JSON_API valueToString(Int value);
|
||||||
std::string JSON_API valueToString(UInt value);
|
JSONCPP_STRING JSON_API valueToString(UInt value);
|
||||||
#endif // if defined(JSON_HAS_INT64)
|
#endif // if defined(JSON_HAS_INT64)
|
||||||
std::string JSON_API valueToString(LargestInt value);
|
JSONCPP_STRING JSON_API valueToString(LargestInt value);
|
||||||
std::string JSON_API valueToString(LargestUInt value);
|
JSONCPP_STRING JSON_API valueToString(LargestUInt value);
|
||||||
std::string JSON_API valueToString(double value);
|
JSONCPP_STRING JSON_API valueToString(double value);
|
||||||
std::string JSON_API valueToString(bool value);
|
JSONCPP_STRING JSON_API valueToString(bool value);
|
||||||
std::string JSON_API valueToQuotedString(const char* value);
|
JSONCPP_STRING JSON_API valueToQuotedString(const char* value);
|
||||||
|
|
||||||
/// \brief Output using the StyledStreamWriter.
|
/// \brief Output using the StyledStreamWriter.
|
||||||
/// \see Json::operator>>()
|
/// \see Json::operator>>()
|
||||||
JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
|
JSON_API JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM&, const Value& root);
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 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
|
||||||
|
|
||||||
"""Tag the sandbox for release, make source and doc tarballs.
|
"""Tag the sandbox for release, make source and doc tarballs.
|
||||||
|
|
||||||
Requires Python 2.6
|
Requires Python 2.6
|
||||||
@@ -14,6 +19,7 @@ python makerelease.py 0.5.0 0.6.0-dev
|
|||||||
Note: This was for Subversion. Now that we are in GitHub, we do not
|
Note: This was for Subversion. Now that we are in GitHub, we do not
|
||||||
need to build versioned tarballs anymore, so makerelease.py is defunct.
|
need to build versioned tarballs anymore, so makerelease.py is defunct.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import os.path
|
import os.path
|
||||||
import subprocess
|
import subprocess
|
||||||
|
102
meson.build
Normal file
102
meson.build
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
project(
|
||||||
|
'jsoncpp',
|
||||||
|
'cpp',
|
||||||
|
version : '1.8.1',
|
||||||
|
default_options : [
|
||||||
|
'buildtype=release',
|
||||||
|
'warning_level=1'],
|
||||||
|
license : 'Public Domain',
|
||||||
|
meson_version : '>= 0.41.1')
|
||||||
|
|
||||||
|
jsoncpp_ver_arr = meson.project_version().split('.')
|
||||||
|
jsoncpp_major_version = jsoncpp_ver_arr[0]
|
||||||
|
jsoncpp_minor_version = jsoncpp_ver_arr[1]
|
||||||
|
jsoncpp_patch_version = jsoncpp_ver_arr[2]
|
||||||
|
|
||||||
|
jsoncpp_cdata = configuration_data()
|
||||||
|
jsoncpp_cdata.set('JSONCPP_VERSION', meson.project_version())
|
||||||
|
jsoncpp_cdata.set('JSONCPP_VERSION_MAJOR', jsoncpp_major_version)
|
||||||
|
jsoncpp_cdata.set('JSONCPP_VERSION_MINOR', jsoncpp_minor_version)
|
||||||
|
jsoncpp_cdata.set('JSONCPP_VERSION_PATCH', jsoncpp_patch_version)
|
||||||
|
|
||||||
|
jsoncpp_gen_sources = configure_file(
|
||||||
|
input : 'src/lib_json/version.h.in',
|
||||||
|
output : 'version.h',
|
||||||
|
configuration : jsoncpp_cdata,
|
||||||
|
install : true,
|
||||||
|
install_dir : join_paths(get_option('prefix'), get_option('includedir'), 'json')
|
||||||
|
)
|
||||||
|
|
||||||
|
jsoncpp_headers = [
|
||||||
|
'include/json/allocator.h',
|
||||||
|
'include/json/assertions.h',
|
||||||
|
'include/json/autolink.h',
|
||||||
|
'include/json/config.h',
|
||||||
|
'include/json/features.h',
|
||||||
|
'include/json/forwards.h',
|
||||||
|
'include/json/json.h',
|
||||||
|
'include/json/reader.h',
|
||||||
|
'include/json/value.h',
|
||||||
|
'include/json/writer.h']
|
||||||
|
jsoncpp_include_directories = include_directories('include')
|
||||||
|
|
||||||
|
install_headers(
|
||||||
|
jsoncpp_headers,
|
||||||
|
subdir : 'json')
|
||||||
|
|
||||||
|
jsoncpp_lib = library(
|
||||||
|
'jsoncpp',
|
||||||
|
[ jsoncpp_gen_sources,
|
||||||
|
jsoncpp_headers,
|
||||||
|
'src/lib_json/json_tool.h',
|
||||||
|
'src/lib_json/json_reader.cpp',
|
||||||
|
'src/lib_json/json_value.cpp',
|
||||||
|
'src/lib_json/json_writer.cpp'],
|
||||||
|
soversion : 18,
|
||||||
|
install : true,
|
||||||
|
include_directories : jsoncpp_include_directories)
|
||||||
|
|
||||||
|
import('pkgconfig').generate(
|
||||||
|
libraries : jsoncpp_lib,
|
||||||
|
version : meson.project_version(),
|
||||||
|
name : 'jsoncpp',
|
||||||
|
filebase : 'jsoncpp',
|
||||||
|
description : 'A C++ library for interacting with JSON')
|
||||||
|
|
||||||
|
# for libraries bundling jsoncpp
|
||||||
|
declare_dependency(
|
||||||
|
include_directories : jsoncpp_include_directories,
|
||||||
|
link_with : jsoncpp_lib,
|
||||||
|
version : meson.project_version(),
|
||||||
|
sources : jsoncpp_gen_sources)
|
||||||
|
|
||||||
|
# tests
|
||||||
|
python = import('python3').find_python()
|
||||||
|
|
||||||
|
jsoncpp_test = executable(
|
||||||
|
'jsoncpp_test',
|
||||||
|
[ 'src/test_lib_json/jsontest.cpp',
|
||||||
|
'src/test_lib_json/jsontest.h',
|
||||||
|
'src/test_lib_json/main.cpp'],
|
||||||
|
include_directories : jsoncpp_include_directories,
|
||||||
|
link_with : jsoncpp_lib,
|
||||||
|
install : false)
|
||||||
|
test(
|
||||||
|
'unittest_jsoncpp_test',
|
||||||
|
jsoncpp_test)
|
||||||
|
|
||||||
|
jsontestrunner = executable(
|
||||||
|
'jsontestrunner',
|
||||||
|
'src/jsontestrunner/main.cpp',
|
||||||
|
include_directories : jsoncpp_include_directories,
|
||||||
|
link_with : jsoncpp_lib,
|
||||||
|
install : false)
|
||||||
|
test(
|
||||||
|
'unittest_jsontestrunner',
|
||||||
|
python,
|
||||||
|
args : [
|
||||||
|
'-B',
|
||||||
|
join_paths(meson.current_source_dir(), 'test/runjsontests.py'),
|
||||||
|
jsontestrunner,
|
||||||
|
join_paths(meson.current_source_dir(), 'test/data')]
|
||||||
|
)
|
@@ -1,7 +1,5 @@
|
|||||||
prefix=@CMAKE_INSTALL_PREFIX@
|
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
|
||||||
exec_prefix=${prefix}
|
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
|
||||||
libdir=${exec_prefix}/@LIBRARY_INSTALL_DIR@
|
|
||||||
includedir=${prefix}/@INCLUDE_INSTALL_DIR@
|
|
||||||
|
|
||||||
Name: jsoncpp
|
Name: jsoncpp
|
||||||
Description: A C++ library for interacting with JSON
|
Description: A C++ library for interacting with JSON
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2009 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
|
||||||
|
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 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
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2010 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
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from SCons.Script import * # the usual scons stuff you get in a SConscript
|
from SCons.Script import * # the usual scons stuff you get in a SConscript
|
||||||
import collections
|
import collections
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 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
|
||||||
|
|
||||||
"""tarball
|
"""tarball
|
||||||
|
|
||||||
Tool-specific initialization for tarball.
|
Tool-specific initialization for tarball.
|
||||||
|
@@ -2,4 +2,4 @@ ADD_SUBDIRECTORY(lib_json)
|
|||||||
IF(JSONCPP_WITH_TESTS)
|
IF(JSONCPP_WITH_TESTS)
|
||||||
ADD_SUBDIRECTORY(jsontestrunner)
|
ADD_SUBDIRECTORY(jsontestrunner)
|
||||||
ADD_SUBDIRECTORY(test_lib_json)
|
ADD_SUBDIRECTORY(test_lib_json)
|
||||||
ENDIF(JSONCPP_WITH_TESTS)
|
ENDIF()
|
||||||
|
@@ -1,18 +1,15 @@
|
|||||||
FIND_PACKAGE(PythonInterp 2.6)
|
FIND_PACKAGE(PythonInterp 2.6)
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
|
||||||
ADD_DEFINITIONS( -DJSON_DLL )
|
|
||||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE(jsontestrunner_exe
|
ADD_EXECUTABLE(jsontestrunner_exe
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
IF(BUILD_SHARED_LIBS)
|
||||||
|
ADD_DEFINITIONS( -DJSON_DLL )
|
||||||
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib)
|
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib)
|
||||||
ELSE(JSONCPP_LIB_BUILD_SHARED)
|
ELSE(BUILD_SHARED_LIBS)
|
||||||
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib_static)
|
TARGET_LINK_LIBRARIES(jsontestrunner_exe jsoncpp_lib_static)
|
||||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
ENDIF()
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
SET_TARGET_PROPERTIES(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)
|
||||||
|
|
||||||
@@ -25,4 +22,4 @@ IF(PYTHONINTERP_FOUND)
|
|||||||
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)
|
||||||
ENDIF(PYTHONINTERP_FOUND)
|
ENDIF()
|
||||||
|
@@ -17,14 +17,14 @@
|
|||||||
|
|
||||||
struct Options
|
struct Options
|
||||||
{
|
{
|
||||||
std::string path;
|
JSONCPP_STRING path;
|
||||||
Json::Features features;
|
Json::Features features;
|
||||||
bool parseOnly;
|
bool parseOnly;
|
||||||
typedef std::string (*writeFuncType)(Json::Value const&);
|
typedef JSONCPP_STRING (*writeFuncType)(Json::Value const&);
|
||||||
writeFuncType write;
|
writeFuncType write;
|
||||||
};
|
};
|
||||||
|
|
||||||
static std::string normalizeFloatingPointStr(double value) {
|
static JSONCPP_STRING normalizeFloatingPointStr(double value) {
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
||||||
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
|
sprintf_s(buffer, sizeof(buffer), "%.16g", value);
|
||||||
@@ -32,18 +32,18 @@ static std::string normalizeFloatingPointStr(double value) {
|
|||||||
snprintf(buffer, sizeof(buffer), "%.16g", value);
|
snprintf(buffer, sizeof(buffer), "%.16g", value);
|
||||||
#endif
|
#endif
|
||||||
buffer[sizeof(buffer) - 1] = 0;
|
buffer[sizeof(buffer) - 1] = 0;
|
||||||
std::string s(buffer);
|
JSONCPP_STRING s(buffer);
|
||||||
std::string::size_type index = s.find_last_of("eE");
|
JSONCPP_STRING::size_type index = s.find_last_of("eE");
|
||||||
if (index != std::string::npos) {
|
if (index != JSONCPP_STRING::npos) {
|
||||||
std::string::size_type hasSign =
|
JSONCPP_STRING::size_type hasSign =
|
||||||
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
||||||
std::string::size_type exponentStartIndex = index + 1 + hasSign;
|
JSONCPP_STRING::size_type exponentStartIndex = index + 1 + hasSign;
|
||||||
std::string normalized = s.substr(0, exponentStartIndex);
|
JSONCPP_STRING normalized = s.substr(0, exponentStartIndex);
|
||||||
std::string::size_type indexDigit =
|
JSONCPP_STRING::size_type indexDigit =
|
||||||
s.find_first_not_of('0', exponentStartIndex);
|
s.find_first_not_of('0', exponentStartIndex);
|
||||||
std::string exponent = "0";
|
JSONCPP_STRING exponent = "0";
|
||||||
if (indexDigit !=
|
if (indexDigit !=
|
||||||
std::string::npos) // There is an exponent different from 0
|
JSONCPP_STRING::npos) // There is an exponent different from 0
|
||||||
{
|
{
|
||||||
exponent = s.substr(indexDigit);
|
exponent = s.substr(indexDigit);
|
||||||
}
|
}
|
||||||
@@ -52,17 +52,18 @@ static std::string normalizeFloatingPointStr(double value) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string readInputTestFile(const char* path) {
|
static JSONCPP_STRING readInputTestFile(const char* path) {
|
||||||
FILE* file = fopen(path, "rb");
|
FILE* file = fopen(path, "rb");
|
||||||
if (!file)
|
if (!file)
|
||||||
return std::string("");
|
return JSONCPP_STRING("");
|
||||||
fseek(file, 0, SEEK_END);
|
fseek(file, 0, SEEK_END);
|
||||||
long size = ftell(file);
|
long const size = ftell(file);
|
||||||
|
unsigned long const usize = static_cast<unsigned long>(size);
|
||||||
fseek(file, 0, SEEK_SET);
|
fseek(file, 0, SEEK_SET);
|
||||||
std::string text;
|
JSONCPP_STRING text;
|
||||||
char* buffer = new char[size + 1];
|
char* buffer = new char[size + 1];
|
||||||
buffer[size] = 0;
|
buffer[size] = 0;
|
||||||
if (fread(buffer, 1, size, file) == (unsigned long)size)
|
if (fread(buffer, 1, usize, file) == usize)
|
||||||
text = buffer;
|
text = buffer;
|
||||||
fclose(file);
|
fclose(file);
|
||||||
delete[] buffer;
|
delete[] buffer;
|
||||||
@@ -70,7 +71,7 @@ static std::string readInputTestFile(const char* path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
|
printValueTree(FILE* fout, Json::Value& value, const JSONCPP_STRING& path = ".") {
|
||||||
if (value.hasComment(Json::commentBefore)) {
|
if (value.hasComment(Json::commentBefore)) {
|
||||||
fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
|
fprintf(fout, "%s\n", value.getComment(Json::commentBefore).c_str());
|
||||||
}
|
}
|
||||||
@@ -104,8 +105,8 @@ printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
|
|||||||
break;
|
break;
|
||||||
case Json::arrayValue: {
|
case Json::arrayValue: {
|
||||||
fprintf(fout, "%s=[]\n", path.c_str());
|
fprintf(fout, "%s=[]\n", path.c_str());
|
||||||
int size = value.size();
|
Json::ArrayIndex size = value.size();
|
||||||
for (int index = 0; index < size; ++index) {
|
for (Json::ArrayIndex index = 0; index < size; ++index) {
|
||||||
static char buffer[16];
|
static char buffer[16];
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
||||||
sprintf_s(buffer, sizeof(buffer), "[%d]", index);
|
sprintf_s(buffer, sizeof(buffer), "[%d]", index);
|
||||||
@@ -119,11 +120,11 @@ printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
|
|||||||
fprintf(fout, "%s={}\n", path.c_str());
|
fprintf(fout, "%s={}\n", path.c_str());
|
||||||
Json::Value::Members members(value.getMemberNames());
|
Json::Value::Members members(value.getMemberNames());
|
||||||
std::sort(members.begin(), members.end());
|
std::sort(members.begin(), members.end());
|
||||||
std::string suffix = *(path.end() - 1) == '.' ? "" : ".";
|
JSONCPP_STRING suffix = *(path.end() - 1) == '.' ? "" : ".";
|
||||||
for (Json::Value::Members::iterator it = members.begin();
|
for (Json::Value::Members::iterator it = members.begin();
|
||||||
it != members.end();
|
it != members.end();
|
||||||
++it) {
|
++it) {
|
||||||
const std::string& name = *it;
|
const JSONCPP_STRING name = *it;
|
||||||
printValueTree(fout, value[name], path + suffix + name);
|
printValueTree(fout, value[name], path + suffix + name);
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
@@ -136,15 +137,15 @@ printValueTree(FILE* fout, Json::Value& value, const std::string& path = ".") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int parseAndSaveValueTree(const std::string& input,
|
static int parseAndSaveValueTree(const JSONCPP_STRING& input,
|
||||||
const std::string& actual,
|
const JSONCPP_STRING& actual,
|
||||||
const std::string& kind,
|
const JSONCPP_STRING& kind,
|
||||||
const Json::Features& features,
|
const Json::Features& features,
|
||||||
bool parseOnly,
|
bool parseOnly,
|
||||||
Json::Value* root)
|
Json::Value* root)
|
||||||
{
|
{
|
||||||
Json::Reader reader(features);
|
Json::Reader reader(features);
|
||||||
bool parsingSuccessful = reader.parse(input, *root);
|
bool parsingSuccessful = reader.parse(input.data(), input.data() + input.size(), *root);
|
||||||
if (!parsingSuccessful) {
|
if (!parsingSuccessful) {
|
||||||
printf("Failed to parse %s file: \n%s\n",
|
printf("Failed to parse %s file: \n%s\n",
|
||||||
kind.c_str(),
|
kind.c_str(),
|
||||||
@@ -162,36 +163,36 @@ static int parseAndSaveValueTree(const std::string& input,
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
// static std::string useFastWriter(Json::Value const& root) {
|
// static JSONCPP_STRING useFastWriter(Json::Value const& root) {
|
||||||
// Json::FastWriter writer;
|
// Json::FastWriter writer;
|
||||||
// writer.enableYAMLCompatibility();
|
// writer.enableYAMLCompatibility();
|
||||||
// return writer.write(root);
|
// return writer.write(root);
|
||||||
// }
|
// }
|
||||||
static std::string useStyledWriter(
|
static JSONCPP_STRING useStyledWriter(
|
||||||
Json::Value const& root)
|
Json::Value const& root)
|
||||||
{
|
{
|
||||||
Json::StyledWriter writer;
|
Json::StyledWriter writer;
|
||||||
return writer.write(root);
|
return writer.write(root);
|
||||||
}
|
}
|
||||||
static std::string useStyledStreamWriter(
|
static JSONCPP_STRING useStyledStreamWriter(
|
||||||
Json::Value const& root)
|
Json::Value const& root)
|
||||||
{
|
{
|
||||||
Json::StyledStreamWriter writer;
|
Json::StyledStreamWriter writer;
|
||||||
std::ostringstream sout;
|
JSONCPP_OSTRINGSTREAM sout;
|
||||||
writer.write(sout, root);
|
writer.write(sout, root);
|
||||||
return sout.str();
|
return sout.str();
|
||||||
}
|
}
|
||||||
static std::string useBuiltStyledStreamWriter(
|
static JSONCPP_STRING useBuiltStyledStreamWriter(
|
||||||
Json::Value const& root)
|
Json::Value const& root)
|
||||||
{
|
{
|
||||||
Json::StreamWriterBuilder builder;
|
Json::StreamWriterBuilder builder;
|
||||||
return Json::writeString(builder, root);
|
return Json::writeString(builder, root);
|
||||||
}
|
}
|
||||||
static int rewriteValueTree(
|
static int rewriteValueTree(
|
||||||
const std::string& rewritePath,
|
const JSONCPP_STRING& rewritePath,
|
||||||
const Json::Value& root,
|
const Json::Value& root,
|
||||||
Options::writeFuncType write,
|
Options::writeFuncType write,
|
||||||
std::string* rewrite)
|
JSONCPP_STRING* rewrite)
|
||||||
{
|
{
|
||||||
*rewrite = write(root);
|
*rewrite = write(root);
|
||||||
FILE* fout = fopen(rewritePath.c_str(), "wt");
|
FILE* fout = fopen(rewritePath.c_str(), "wt");
|
||||||
@@ -204,13 +205,13 @@ static int rewriteValueTree(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string removeSuffix(const std::string& path,
|
static JSONCPP_STRING removeSuffix(const JSONCPP_STRING& path,
|
||||||
const std::string& extension) {
|
const JSONCPP_STRING& extension) {
|
||||||
if (extension.length() >= path.length())
|
if (extension.length() >= path.length())
|
||||||
return std::string("");
|
return JSONCPP_STRING("");
|
||||||
std::string suffix = path.substr(path.length() - extension.length());
|
JSONCPP_STRING suffix = path.substr(path.length() - extension.length());
|
||||||
if (suffix != extension)
|
if (suffix != extension)
|
||||||
return std::string("");
|
return JSONCPP_STRING("");
|
||||||
return path.substr(0, path.length() - extension.length());
|
return path.substr(0, path.length() - extension.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -237,18 +238,18 @@ static int parseCommandLine(
|
|||||||
return printUsage(argv);
|
return printUsage(argv);
|
||||||
}
|
}
|
||||||
int index = 1;
|
int index = 1;
|
||||||
if (std::string(argv[index]) == "--json-checker") {
|
if (JSONCPP_STRING(argv[index]) == "--json-checker") {
|
||||||
opts->features = Json::Features::strictMode();
|
opts->features = Json::Features::strictMode();
|
||||||
opts->parseOnly = true;
|
opts->parseOnly = true;
|
||||||
++index;
|
++index;
|
||||||
}
|
}
|
||||||
if (std::string(argv[index]) == "--json-config") {
|
if (JSONCPP_STRING(argv[index]) == "--json-config") {
|
||||||
printConfig();
|
printConfig();
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
if (std::string(argv[index]) == "--json-writer") {
|
if (JSONCPP_STRING(argv[index]) == "--json-writer") {
|
||||||
++index;
|
++index;
|
||||||
std::string const writerName(argv[index++]);
|
JSONCPP_STRING const writerName(argv[index++]);
|
||||||
if (writerName == "StyledWriter") {
|
if (writerName == "StyledWriter") {
|
||||||
opts->write = &useStyledWriter;
|
opts->write = &useStyledWriter;
|
||||||
} else if (writerName == "StyledStreamWriter") {
|
} else if (writerName == "StyledStreamWriter") {
|
||||||
@@ -270,22 +271,22 @@ static int runTest(Options const& opts)
|
|||||||
{
|
{
|
||||||
int exitCode = 0;
|
int exitCode = 0;
|
||||||
|
|
||||||
std::string input = readInputTestFile(opts.path.c_str());
|
JSONCPP_STRING input = readInputTestFile(opts.path.c_str());
|
||||||
if (input.empty()) {
|
if (input.empty()) {
|
||||||
printf("Failed to read input or empty input: %s\n", opts.path.c_str());
|
printf("Failed to read input or empty input: %s\n", opts.path.c_str());
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string basePath = removeSuffix(opts.path, ".json");
|
JSONCPP_STRING basePath = removeSuffix(opts.path, ".json");
|
||||||
if (!opts.parseOnly && basePath.empty()) {
|
if (!opts.parseOnly && basePath.empty()) {
|
||||||
printf("Bad input path. Path does not end with '.expected':\n%s\n",
|
printf("Bad input path. Path does not end with '.expected':\n%s\n",
|
||||||
opts.path.c_str());
|
opts.path.c_str());
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string const actualPath = basePath + ".actual";
|
JSONCPP_STRING const actualPath = basePath + ".actual";
|
||||||
std::string const rewritePath = basePath + ".rewrite";
|
JSONCPP_STRING const rewritePath = basePath + ".rewrite";
|
||||||
std::string const rewriteActualPath = basePath + ".actual-rewrite";
|
JSONCPP_STRING const rewriteActualPath = basePath + ".actual-rewrite";
|
||||||
|
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
exitCode = parseAndSaveValueTree(
|
exitCode = parseAndSaveValueTree(
|
||||||
@@ -294,7 +295,7 @@ static int runTest(Options const& opts)
|
|||||||
if (exitCode || opts.parseOnly) {
|
if (exitCode || opts.parseOnly) {
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
std::string rewrite;
|
JSONCPP_STRING rewrite;
|
||||||
exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite);
|
exitCode = rewriteValueTree(rewritePath, root, opts.write, &rewrite);
|
||||||
if (exitCode) {
|
if (exitCode) {
|
||||||
return exitCode;
|
return exitCode;
|
||||||
@@ -310,12 +311,12 @@ static int runTest(Options const& opts)
|
|||||||
}
|
}
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
Options opts;
|
Options opts;
|
||||||
|
try {
|
||||||
int exitCode = parseCommandLine(argc, argv, &opts);
|
int exitCode = parseCommandLine(argc, argv, &opts);
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
printf("Failed to parse command-line.");
|
printf("Failed to parse command-line.");
|
||||||
return exitCode;
|
return exitCode;
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
return runTest(opts);
|
return runTest(opts);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e) {
|
catch (const std::exception& e) {
|
||||||
|
@@ -1,20 +1,41 @@
|
|||||||
OPTION(JSONCPP_LIB_BUILD_SHARED "Build jsoncpp_lib as a shared library." OFF)
|
IF( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
OPTION(JSONCPP_LIB_BUILD_STATIC "Build jsoncpp_lib static library." ON)
|
|
||||||
|
|
||||||
IF(BUILD_SHARED_LIBS)
|
|
||||||
SET(JSONCPP_LIB_BUILD_SHARED ON)
|
|
||||||
ENDIF(BUILD_SHARED_LIBS)
|
|
||||||
|
|
||||||
if( CMAKE_COMPILER_IS_GNUCXX )
|
|
||||||
#Get compiler version.
|
#Get compiler version.
|
||||||
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
EXECUTE_PROCESS( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
|
||||||
OUTPUT_VARIABLE GNUCXX_VERSION )
|
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 )
|
IF( GNUCXX_VERSION VERSION_GREATER 4.1.2 )
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing")
|
||||||
endif()
|
ENDIF()
|
||||||
endif( CMAKE_COMPILER_IS_GNUCXX )
|
ENDIF( CMAKE_COMPILER_IS_GNUCXX )
|
||||||
|
|
||||||
|
INCLUDE(CheckIncludeFileCXX)
|
||||||
|
INCLUDE(CheckTypeSize)
|
||||||
|
INCLUDE(CheckStructHasMember)
|
||||||
|
INCLUDE(CheckCXXSymbolExists)
|
||||||
|
|
||||||
|
check_include_file_cxx(clocale HAVE_CLOCALE)
|
||||||
|
check_cxx_symbol_exists(localeconv clocale HAVE_LOCALECONV)
|
||||||
|
|
||||||
|
IF(CMAKE_VERSION VERSION_LESS 3.0.0)
|
||||||
|
# The "LANGUAGE CXX" parameter is not supported in CMake versions below 3,
|
||||||
|
# so the C compiler and header has to be used.
|
||||||
|
check_include_file(locale.h HAVE_LOCALE_H)
|
||||||
|
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))
|
||||||
|
MESSAGE(WARNING "Locale functionality is not supported")
|
||||||
|
ADD_DEFINITIONS(-DJSONCPP_NO_LOCALE_SUPPORT)
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
SET( JSONCPP_INCLUDE_DIR ../../include )
|
SET( JSONCPP_INCLUDE_DIR ../../include )
|
||||||
|
|
||||||
@@ -44,42 +65,49 @@ IF(JSONCPP_WITH_CMAKE_PACKAGE)
|
|||||||
SET(INSTALL_EXPORT EXPORT jsoncpp)
|
SET(INSTALL_EXPORT EXPORT jsoncpp)
|
||||||
ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
|
ELSE(JSONCPP_WITH_CMAKE_PACKAGE)
|
||||||
SET(INSTALL_EXPORT)
|
SET(INSTALL_EXPORT)
|
||||||
ENDIF(JSONCPP_WITH_CMAKE_PACKAGE)
|
ENDIF()
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
IF(BUILD_SHARED_LIBS)
|
||||||
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
|
ADD_DEFINITIONS( -DJSON_DLL_BUILD )
|
||||||
ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
ADD_LIBRARY(jsoncpp_lib SHARED ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
||||||
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
|
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
|
||||||
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp )
|
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
|
||||||
|
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
|
||||||
|
|
||||||
|
# Set library's runtime search path on OSX
|
||||||
|
IF(APPLE)
|
||||||
|
SET_TARGET_PROPERTIES( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
|
||||||
|
ENDIF()
|
||||||
|
|
||||||
INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
INSTALL( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
|
||||||
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR})
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
|
||||||
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||||
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC
|
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib PUBLIC
|
||||||
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>)
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>)
|
||||||
ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
ENDIF()
|
||||||
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_STATIC)
|
IF(BUILD_STATIC_LIBS)
|
||||||
ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
ADD_LIBRARY(jsoncpp_lib_static STATIC ${PUBLIC_HEADERS} ${jsoncpp_sources})
|
||||||
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_VERSION_MAJOR})
|
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
|
||||||
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp )
|
SET_TARGET_PROPERTIES( jsoncpp_lib_static PROPERTIES OUTPUT_NAME jsoncpp
|
||||||
|
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
|
||||||
|
|
||||||
INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT}
|
INSTALL( TARGETS jsoncpp_lib_static ${INSTALL_EXPORT}
|
||||||
RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR}
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
LIBRARY DESTINATION ${LIBRARY_INSTALL_DIR}
|
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
|
||||||
ARCHIVE DESTINATION ${ARCHIVE_INSTALL_DIR})
|
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
|
||||||
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
IF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
||||||
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib_static PUBLIC
|
TARGET_INCLUDE_DIRECTORIES( jsoncpp_lib_static PUBLIC
|
||||||
$<INSTALL_INTERFACE:${INCLUDE_INSTALL_DIR}>
|
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
|
||||||
)
|
)
|
||||||
ENDIF(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
|
ENDIF()
|
||||||
|
|
||||||
ENDIF()
|
ENDIF()
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
// Copyright 2007-2011 Baptiste Lepilleur
|
// Copyright 2007-2011 Baptiste Lepilleur
|
||||||
|
// Copyright (C) 2016 InfoTeCS JSC. All rights reserved.
|
||||||
// Distributed under MIT license, or public domain if desired and
|
// Distributed under MIT license, or public domain if desired and
|
||||||
// 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
|
||||||
@@ -17,23 +18,43 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <limits>
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
#if defined(_MSC_VER)
|
||||||
|
#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#elif _MSC_VER >= 1900 // VC++ 14.0 and above
|
||||||
|
#define snprintf std::snprintf
|
||||||
|
#else
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
#endif
|
#endif
|
||||||
|
#elif defined(__ANDROID__) || defined(__QNXNTO__)
|
||||||
|
#define snprintf snprintf
|
||||||
|
#elif __cplusplus >= 201103L
|
||||||
|
#if !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
|
#define snprintf std::snprintf
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__QNXNTO__)
|
||||||
|
#define sscanf std::sscanf
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
|
#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
|
||||||
// Disable warning about strdup being deprecated.
|
// Disable warning about strdup being deprecated.
|
||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int const stackLimit_g = 1000;
|
// Define JSONCPP_DEPRECATED_STACK_LIMIT as an appropriate integer at compile time to change the stack limit
|
||||||
static int stackDepth_g = 0; // see readValue()
|
#if !defined(JSONCPP_DEPRECATED_STACK_LIMIT)
|
||||||
|
#define JSONCPP_DEPRECATED_STACK_LIMIT 1000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static size_t const stackLimit_g = JSONCPP_DEPRECATED_STACK_LIMIT; // see readValue()
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
||||||
typedef std::unique_ptr<CharReader> CharReaderPtr;
|
typedef std::unique_ptr<CharReader> CharReaderPtr;
|
||||||
#else
|
#else
|
||||||
typedef std::auto_ptr<CharReader> CharReaderPtr;
|
typedef std::auto_ptr<CharReader> CharReaderPtr;
|
||||||
@@ -82,7 +103,8 @@ Reader::Reader(const Features& features)
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
Reader::parse(const std::string& document, Value& root, bool collectComments) {
|
Reader::parse(const std::string& document, Value& root, bool collectComments) {
|
||||||
document_ = document;
|
JSONCPP_STRING documentCopy(document.data(), document.data() + document.capacity());
|
||||||
|
std::swap(documentCopy, document_);
|
||||||
const char* begin = document_.c_str();
|
const char* begin = document_.c_str();
|
||||||
const char* end = begin + document_.length();
|
const char* end = begin + document_.length();
|
||||||
return parse(begin, end, root, collectComments);
|
return parse(begin, end, root, collectComments);
|
||||||
@@ -94,11 +116,11 @@ bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
|
|||||||
// Those would allow streamed input from a file, if parse() were a
|
// Those would allow streamed input from a file, if parse() were a
|
||||||
// template function.
|
// template function.
|
||||||
|
|
||||||
// Since std::string is reference-counted, this at least does not
|
// Since JSONCPP_STRING is reference-counted, this at least does not
|
||||||
// create an extra copy.
|
// create an extra copy.
|
||||||
std::string doc;
|
JSONCPP_STRING doc;
|
||||||
std::getline(sin, doc, (char)EOF);
|
std::getline(sin, doc, (char)EOF);
|
||||||
return parse(doc, root, collectComments);
|
return parse(doc.data(), doc.data() + doc.size(), root, collectComments);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::parse(const char* beginDoc,
|
bool Reader::parse(const char* beginDoc,
|
||||||
@@ -115,13 +137,12 @@ bool Reader::parse(const char* beginDoc,
|
|||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = 0;
|
lastValueEnd_ = 0;
|
||||||
lastValue_ = 0;
|
lastValue_ = 0;
|
||||||
commentsBefore_ = "";
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
stackDepth_g = 0; // Yes, this is bad coding, but options are limited.
|
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
@@ -144,12 +165,10 @@ bool Reader::parse(const char* beginDoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readValue() {
|
bool Reader::readValue() {
|
||||||
// This is a non-reentrant way to support a stackLimit. Terrible!
|
// readValue() may call itself only if it calls readObject() or ReadArray().
|
||||||
// But this deprecated class has a security problem: Bad input can
|
// These methods execute nodes_.push() just before and nodes_.pop)() just after calling readValue().
|
||||||
// cause a seg-fault. This seems like a fair, binary-compatible way
|
// parse() executes one nodes_.push(), so > instead of >=.
|
||||||
// to prevent the problem.
|
if (nodes_.size() > stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
if (stackDepth_g >= stackLimit_g) throw std::runtime_error("Exceeded stackLimit in readValue().");
|
|
||||||
++stackDepth_g;
|
|
||||||
|
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
@@ -157,7 +176,7 @@ bool Reader::readValue() {
|
|||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
currentValue().setComment(commentsBefore_, commentBefore);
|
currentValue().setComment(commentsBefore_, commentBefore);
|
||||||
commentsBefore_ = "";
|
commentsBefore_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (token.type_) {
|
switch (token.type_) {
|
||||||
@@ -223,7 +242,6 @@ bool Reader::readValue() {
|
|||||||
lastValue_ = ¤tValue();
|
lastValue_ = ¤tValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
--stackDepth_g;
|
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,9 +370,9 @@ bool Reader::readComment() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
|
static JSONCPP_STRING normalizeEOL(Reader::Location begin, Reader::Location end) {
|
||||||
std::string normalized;
|
JSONCPP_STRING normalized;
|
||||||
normalized.reserve(end - begin);
|
normalized.reserve(static_cast<size_t>(end - begin));
|
||||||
Reader::Location current = begin;
|
Reader::Location current = begin;
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
char c = *current++;
|
char c = *current++;
|
||||||
@@ -374,7 +392,7 @@ static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
|
|||||||
void
|
void
|
||||||
Reader::addComment(Location begin, Location end, CommentPlacement placement) {
|
Reader::addComment(Location begin, Location end, CommentPlacement placement) {
|
||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const std::string& normalized = normalizeEOL(begin, end);
|
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != 0);
|
assert(lastValue_ != 0);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
@@ -384,7 +402,7 @@ Reader::addComment(Location begin, Location end, CommentPlacement placement) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readCStyleComment() {
|
bool Reader::readCStyleComment() {
|
||||||
while (current_ != end_) {
|
while ((current_ + 1) < end_) {
|
||||||
Char c = getNextChar();
|
Char c = getNextChar();
|
||||||
if (c == '*' && *current_ == '/')
|
if (c == '*' && *current_ == '/')
|
||||||
break;
|
break;
|
||||||
@@ -413,25 +431,25 @@ void Reader::readNumber() {
|
|||||||
char c = '0'; // stopgap for already consumed character
|
char c = '0'; // stopgap for already consumed character
|
||||||
// integral part
|
// integral part
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
// fractional part
|
// fractional part
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
}
|
}
|
||||||
// exponential part
|
// exponential part
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
if (c == '+' || c == '-')
|
if (c == '+' || c == '-')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::readString() {
|
bool Reader::readString() {
|
||||||
Char c = 0;
|
Char c = '\0';
|
||||||
while (current_ != end_) {
|
while (current_ != end_) {
|
||||||
c = getNextChar();
|
c = getNextChar();
|
||||||
if (c == '\\')
|
if (c == '\\')
|
||||||
@@ -444,7 +462,7 @@ bool Reader::readString() {
|
|||||||
|
|
||||||
bool Reader::readObject(Token& tokenStart) {
|
bool Reader::readObject(Token& tokenStart) {
|
||||||
Token tokenName;
|
Token tokenName;
|
||||||
std::string name;
|
JSONCPP_STRING name;
|
||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
@@ -456,7 +474,7 @@ bool Reader::readObject(Token& tokenStart) {
|
|||||||
break;
|
break;
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
||||||
return true;
|
return true;
|
||||||
name = "";
|
name.clear();
|
||||||
if (tokenName.type_ == tokenString) {
|
if (tokenName.type_ == tokenString) {
|
||||||
if (!decodeString(tokenName, name))
|
if (!decodeString(tokenName, name))
|
||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
@@ -464,7 +482,7 @@ bool Reader::readObject(Token& tokenStart) {
|
|||||||
Value numberName;
|
Value numberName;
|
||||||
if (!decodeNumber(tokenName, numberName))
|
if (!decodeNumber(tokenName, numberName))
|
||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
name = numberName.asString();
|
name = JSONCPP_STRING(numberName.asCString());
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -503,7 +521,7 @@ bool Reader::readArray(Token& tokenStart) {
|
|||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
if (*current_ == ']') // empty array
|
if (current_ != end_ && *current_ == ']') // empty array
|
||||||
{
|
{
|
||||||
Token endArray;
|
Token endArray;
|
||||||
readToken(endArray);
|
readToken(endArray);
|
||||||
@@ -556,7 +574,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
++current;
|
++current;
|
||||||
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
|
// TODO: Help the compiler do the div and mod at compile time or get rid of them.
|
||||||
Value::LargestUInt maxIntegerValue =
|
Value::LargestUInt maxIntegerValue =
|
||||||
isNegative ? Value::LargestUInt(-Value::minLargestInt)
|
isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
|
||||||
: Value::maxLargestUInt;
|
: Value::maxLargestUInt;
|
||||||
Value::LargestUInt threshold = maxIntegerValue / 10;
|
Value::LargestUInt threshold = maxIntegerValue / 10;
|
||||||
Value::LargestUInt value = 0;
|
Value::LargestUInt value = 0;
|
||||||
@@ -564,7 +582,7 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
return decodeDouble(token, decoded);
|
||||||
Value::UInt digit(c - '0');
|
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||||
if (value >= threshold) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, b) this is the last digit, and
|
// a) we've only just touched the limit, b) this is the last digit, and
|
||||||
@@ -577,7 +595,9 @@ bool Reader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
}
|
}
|
||||||
value = value * 10 + digit;
|
value = value * 10 + digit;
|
||||||
}
|
}
|
||||||
if (isNegative)
|
if (isNegative && value == maxIntegerValue)
|
||||||
|
decoded = Value::minLargestInt;
|
||||||
|
else if (isNegative)
|
||||||
decoded = -Value::LargestInt(value);
|
decoded = -Value::LargestInt(value);
|
||||||
else if (value <= Value::LargestUInt(Value::maxInt))
|
else if (value <= Value::LargestUInt(Value::maxInt))
|
||||||
decoded = Value::LargestInt(value);
|
decoded = Value::LargestInt(value);
|
||||||
@@ -598,34 +618,10 @@ 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;
|
||||||
const int bufferSize = 32;
|
JSONCPP_STRING buffer(token.start_, token.end_);
|
||||||
int count;
|
JSONCPP_ISTRINGSTREAM is(buffer);
|
||||||
int length = int(token.end_ - token.start_);
|
if (!(is >> value))
|
||||||
|
return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
|
||||||
// Sanity check to avoid buffer overflow exploits.
|
|
||||||
if (length < 0) {
|
|
||||||
return addError("Unable to parse token length", token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Avoid using a string constant for the format control string given to
|
|
||||||
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
|
|
||||||
// info:
|
|
||||||
//
|
|
||||||
// http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
|
|
||||||
char format[] = "%lf";
|
|
||||||
|
|
||||||
if (length <= bufferSize) {
|
|
||||||
Char buffer[bufferSize + 1];
|
|
||||||
memcpy(buffer, token.start_, length);
|
|
||||||
buffer[length] = 0;
|
|
||||||
count = sscanf(buffer, format, &value);
|
|
||||||
} else {
|
|
||||||
std::string buffer(token.start_, token.end_);
|
|
||||||
count = sscanf(buffer.c_str(), format, &value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count != 1)
|
|
||||||
return addError("'" + std::string(token.start_, token.end_) +
|
|
||||||
"' is not a number.",
|
"' is not a number.",
|
||||||
token);
|
token);
|
||||||
decoded = value;
|
decoded = value;
|
||||||
@@ -633,7 +629,7 @@ bool Reader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::decodeString(Token& token) {
|
bool Reader::decodeString(Token& token) {
|
||||||
std::string decoded_string;
|
JSONCPP_STRING decoded_string;
|
||||||
if (!decodeString(token, decoded_string))
|
if (!decodeString(token, decoded_string))
|
||||||
return false;
|
return false;
|
||||||
Value decoded(decoded_string);
|
Value decoded(decoded_string);
|
||||||
@@ -643,8 +639,8 @@ bool Reader::decodeString(Token& token) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::decodeString(Token& token, std::string& decoded) {
|
bool Reader::decodeString(Token& token, JSONCPP_STRING& decoded) {
|
||||||
decoded.reserve(token.end_ - token.start_ - 2);
|
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
|
||||||
Location current = token.start_ + 1; // skip '"'
|
Location current = token.start_ + 1; // skip '"'
|
||||||
Location end = token.end_ - 1; // do not include '"'
|
Location end = token.end_ - 1; // do not include '"'
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
@@ -728,13 +724,13 @@ bool Reader::decodeUnicodeCodePoint(Token& token,
|
|||||||
bool Reader::decodeUnicodeEscapeSequence(Token& token,
|
bool Reader::decodeUnicodeEscapeSequence(Token& token,
|
||||||
Location& current,
|
Location& current,
|
||||||
Location end,
|
Location end,
|
||||||
unsigned int& unicode) {
|
unsigned int& ret_unicode) {
|
||||||
if (end - current < 4)
|
if (end - current < 4)
|
||||||
return addError(
|
return addError(
|
||||||
"Bad unicode escape sequence in string: four digits expected.",
|
"Bad unicode escape sequence in string: four digits expected.",
|
||||||
token,
|
token,
|
||||||
current);
|
current);
|
||||||
unicode = 0;
|
int unicode = 0;
|
||||||
for (int index = 0; index < 4; ++index) {
|
for (int index = 0; index < 4; ++index) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
unicode *= 16;
|
unicode *= 16;
|
||||||
@@ -750,11 +746,12 @@ bool Reader::decodeUnicodeEscapeSequence(Token& token,
|
|||||||
token,
|
token,
|
||||||
current);
|
current);
|
||||||
}
|
}
|
||||||
|
ret_unicode = static_cast<unsigned int>(unicode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
Reader::addError(const std::string& message, Token& token, Location extra) {
|
Reader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
|
||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.token_ = token;
|
info.token_ = token;
|
||||||
info.message_ = message;
|
info.message_ = message;
|
||||||
@@ -764,7 +761,7 @@ Reader::addError(const std::string& message, Token& token, Location extra) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::recoverFromError(TokenType skipUntilToken) {
|
bool Reader::recoverFromError(TokenType skipUntilToken) {
|
||||||
int errorCount = int(errors_.size());
|
size_t const errorCount = errors_.size();
|
||||||
Token skip;
|
Token skip;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!readToken(skip))
|
if (!readToken(skip))
|
||||||
@@ -776,7 +773,7 @@ bool Reader::recoverFromError(TokenType skipUntilToken) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::addErrorAndRecover(const std::string& message,
|
bool Reader::addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
Token& token,
|
Token& token,
|
||||||
TokenType skipUntilToken) {
|
TokenType skipUntilToken) {
|
||||||
addError(message, token);
|
addError(message, token);
|
||||||
@@ -814,29 +811,21 @@ void Reader::getLocationLineAndColumn(Location location,
|
|||||||
++line;
|
++line;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Reader::getLocationLineAndColumn(Location location) const {
|
JSONCPP_STRING Reader::getLocationLineAndColumn(Location location) const {
|
||||||
int line, column;
|
int line, column;
|
||||||
getLocationLineAndColumn(location, line, column);
|
getLocationLineAndColumn(location, line, column);
|
||||||
char buffer[18 + 16 + 16 + 1];
|
char buffer[18 + 16 + 16 + 1];
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
|
||||||
#if defined(WINCE)
|
|
||||||
_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
|
||||||
#else
|
|
||||||
sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
||||||
#endif
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated. Preserved for backward compatibility
|
// Deprecated. Preserved for backward compatibility
|
||||||
std::string Reader::getFormatedErrorMessages() const {
|
JSONCPP_STRING Reader::getFormatedErrorMessages() const {
|
||||||
return getFormattedErrorMessages();
|
return getFormattedErrorMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Reader::getFormattedErrorMessages() const {
|
JSONCPP_STRING Reader::getFormattedErrorMessages() const {
|
||||||
std::string formattedMessage;
|
JSONCPP_STRING formattedMessage;
|
||||||
for (Errors::const_iterator itError = errors_.begin();
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
itError != errors_.end();
|
itError != errors_.end();
|
||||||
++itError) {
|
++itError) {
|
||||||
@@ -866,8 +855,8 @@ std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
|
|||||||
return allErrors;
|
return allErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::pushError(const Value& value, const std::string& message) {
|
bool Reader::pushError(const Value& value, const JSONCPP_STRING& message) {
|
||||||
size_t length = end_ - begin_;
|
ptrdiff_t const length = end_ - begin_;
|
||||||
if(value.getOffsetStart() > length
|
if(value.getOffsetStart() > length
|
||||||
|| value.getOffsetLimit() > length)
|
|| value.getOffsetLimit() > length)
|
||||||
return false;
|
return false;
|
||||||
@@ -883,8 +872,8 @@ bool Reader::pushError(const Value& value, const std::string& message) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
|
bool Reader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
|
||||||
size_t length = end_ - begin_;
|
ptrdiff_t const length = end_ - begin_;
|
||||||
if(value.getOffsetStart() > length
|
if(value.getOffsetStart() > length
|
||||||
|| value.getOffsetLimit() > length
|
|| value.getOffsetLimit() > length
|
||||||
|| extra.getOffsetLimit() > length)
|
|| extra.getOffsetLimit() > length)
|
||||||
@@ -909,7 +898,6 @@ bool Reader::good() const {
|
|||||||
class OurFeatures {
|
class OurFeatures {
|
||||||
public:
|
public:
|
||||||
static OurFeatures all();
|
static OurFeatures all();
|
||||||
OurFeatures();
|
|
||||||
bool allowComments_;
|
bool allowComments_;
|
||||||
bool strictRoot_;
|
bool strictRoot_;
|
||||||
bool allowDroppedNullPlaceholders_;
|
bool allowDroppedNullPlaceholders_;
|
||||||
@@ -917,20 +905,13 @@ public:
|
|||||||
bool allowSingleQuotes_;
|
bool allowSingleQuotes_;
|
||||||
bool failIfExtra_;
|
bool failIfExtra_;
|
||||||
bool rejectDupKeys_;
|
bool rejectDupKeys_;
|
||||||
|
bool allowSpecialFloats_;
|
||||||
int stackLimit_;
|
int stackLimit_;
|
||||||
}; // OurFeatures
|
}; // OurFeatures
|
||||||
|
|
||||||
// exact copy of Implementation of class Features
|
// exact copy of Implementation of class Features
|
||||||
// ////////////////////////////////
|
// ////////////////////////////////
|
||||||
|
|
||||||
OurFeatures::OurFeatures()
|
|
||||||
: allowComments_(true), strictRoot_(false)
|
|
||||||
, allowDroppedNullPlaceholders_(false), allowNumericKeys_(false)
|
|
||||||
, allowSingleQuotes_(false)
|
|
||||||
, failIfExtra_(false)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
OurFeatures OurFeatures::all() { return OurFeatures(); }
|
OurFeatures OurFeatures::all() { return OurFeatures(); }
|
||||||
|
|
||||||
// Implementation of class Reader
|
// Implementation of class Reader
|
||||||
@@ -942,9 +923,9 @@ public:
|
|||||||
typedef char Char;
|
typedef char Char;
|
||||||
typedef const Char* Location;
|
typedef const Char* Location;
|
||||||
struct StructuredError {
|
struct StructuredError {
|
||||||
size_t offset_start;
|
ptrdiff_t offset_start;
|
||||||
size_t offset_limit;
|
ptrdiff_t offset_limit;
|
||||||
std::string message;
|
JSONCPP_STRING message;
|
||||||
};
|
};
|
||||||
|
|
||||||
OurReader(OurFeatures const& features);
|
OurReader(OurFeatures const& features);
|
||||||
@@ -952,10 +933,10 @@ public:
|
|||||||
const char* endDoc,
|
const char* endDoc,
|
||||||
Value& root,
|
Value& root,
|
||||||
bool collectComments = true);
|
bool collectComments = true);
|
||||||
std::string getFormattedErrorMessages() const;
|
JSONCPP_STRING getFormattedErrorMessages() const;
|
||||||
std::vector<StructuredError> getStructuredErrors() const;
|
std::vector<StructuredError> getStructuredErrors() const;
|
||||||
bool pushError(const Value& value, const std::string& message);
|
bool pushError(const Value& value, const JSONCPP_STRING& message);
|
||||||
bool pushError(const Value& value, const std::string& message, const Value& extra);
|
bool pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra);
|
||||||
bool good() const;
|
bool good() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -973,6 +954,9 @@ private:
|
|||||||
tokenTrue,
|
tokenTrue,
|
||||||
tokenFalse,
|
tokenFalse,
|
||||||
tokenNull,
|
tokenNull,
|
||||||
|
tokenNaN,
|
||||||
|
tokenPosInf,
|
||||||
|
tokenNegInf,
|
||||||
tokenArraySeparator,
|
tokenArraySeparator,
|
||||||
tokenMemberSeparator,
|
tokenMemberSeparator,
|
||||||
tokenComment,
|
tokenComment,
|
||||||
@@ -989,7 +973,7 @@ private:
|
|||||||
class ErrorInfo {
|
class ErrorInfo {
|
||||||
public:
|
public:
|
||||||
Token token_;
|
Token token_;
|
||||||
std::string message_;
|
JSONCPP_STRING message_;
|
||||||
Location extra_;
|
Location extra_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1003,14 +987,14 @@ private:
|
|||||||
bool readCppStyleComment();
|
bool readCppStyleComment();
|
||||||
bool readString();
|
bool readString();
|
||||||
bool readStringSingleQuote();
|
bool readStringSingleQuote();
|
||||||
void readNumber();
|
bool readNumber(bool checkInf);
|
||||||
bool readValue();
|
bool readValue();
|
||||||
bool readObject(Token& token);
|
bool readObject(Token& token);
|
||||||
bool readArray(Token& token);
|
bool readArray(Token& token);
|
||||||
bool decodeNumber(Token& token);
|
bool decodeNumber(Token& token);
|
||||||
bool decodeNumber(Token& token, Value& decoded);
|
bool decodeNumber(Token& token, Value& decoded);
|
||||||
bool decodeString(Token& token);
|
bool decodeString(Token& token);
|
||||||
bool decodeString(Token& token, std::string& decoded);
|
bool decodeString(Token& token, JSONCPP_STRING& decoded);
|
||||||
bool decodeDouble(Token& token);
|
bool decodeDouble(Token& token);
|
||||||
bool decodeDouble(Token& token, Value& decoded);
|
bool decodeDouble(Token& token, Value& decoded);
|
||||||
bool decodeUnicodeCodePoint(Token& token,
|
bool decodeUnicodeCodePoint(Token& token,
|
||||||
@@ -1021,9 +1005,9 @@ private:
|
|||||||
Location& current,
|
Location& current,
|
||||||
Location end,
|
Location end,
|
||||||
unsigned int& unicode);
|
unsigned int& unicode);
|
||||||
bool addError(const std::string& message, Token& token, Location extra = 0);
|
bool addError(const JSONCPP_STRING& message, Token& token, Location extra = 0);
|
||||||
bool recoverFromError(TokenType skipUntilToken);
|
bool recoverFromError(TokenType skipUntilToken);
|
||||||
bool addErrorAndRecover(const std::string& message,
|
bool addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
Token& token,
|
Token& token,
|
||||||
TokenType skipUntilToken);
|
TokenType skipUntilToken);
|
||||||
void skipUntilSpace();
|
void skipUntilSpace();
|
||||||
@@ -1031,21 +1015,20 @@ private:
|
|||||||
Char getNextChar();
|
Char getNextChar();
|
||||||
void
|
void
|
||||||
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
getLocationLineAndColumn(Location location, int& line, int& column) const;
|
||||||
std::string getLocationLineAndColumn(Location location) const;
|
JSONCPP_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);
|
void skipCommentTokens(Token& token);
|
||||||
|
|
||||||
typedef std::stack<Value*> Nodes;
|
typedef std::stack<Value*> Nodes;
|
||||||
Nodes nodes_;
|
Nodes nodes_;
|
||||||
Errors errors_;
|
Errors errors_;
|
||||||
std::string document_;
|
JSONCPP_STRING document_;
|
||||||
Location begin_;
|
Location begin_;
|
||||||
Location end_;
|
Location end_;
|
||||||
Location current_;
|
Location current_;
|
||||||
Location lastValueEnd_;
|
Location lastValueEnd_;
|
||||||
Value* lastValue_;
|
Value* lastValue_;
|
||||||
std::string commentsBefore_;
|
JSONCPP_STRING commentsBefore_;
|
||||||
int stackDepth_;
|
|
||||||
|
|
||||||
OurFeatures const features_;
|
OurFeatures const features_;
|
||||||
bool collectComments_;
|
bool collectComments_;
|
||||||
@@ -1055,7 +1038,8 @@ private:
|
|||||||
|
|
||||||
OurReader::OurReader(OurFeatures const& features)
|
OurReader::OurReader(OurFeatures const& features)
|
||||||
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
: errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
|
||||||
lastValue_(), commentsBefore_(), features_(features), collectComments_() {
|
lastValue_(), commentsBefore_(),
|
||||||
|
features_(features), collectComments_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::parse(const char* beginDoc,
|
bool OurReader::parse(const char* beginDoc,
|
||||||
@@ -1072,18 +1056,17 @@ bool OurReader::parse(const char* beginDoc,
|
|||||||
current_ = begin_;
|
current_ = begin_;
|
||||||
lastValueEnd_ = 0;
|
lastValueEnd_ = 0;
|
||||||
lastValue_ = 0;
|
lastValue_ = 0;
|
||||||
commentsBefore_ = "";
|
commentsBefore_.clear();
|
||||||
errors_.clear();
|
errors_.clear();
|
||||||
while (!nodes_.empty())
|
while (!nodes_.empty())
|
||||||
nodes_.pop();
|
nodes_.pop();
|
||||||
nodes_.push(&root);
|
nodes_.push(&root);
|
||||||
|
|
||||||
stackDepth_ = 0;
|
|
||||||
bool successful = readValue();
|
bool successful = readValue();
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
if (features_.failIfExtra_) {
|
if (features_.failIfExtra_) {
|
||||||
if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
|
if ((features_.strictRoot_ || token.type_ != tokenError) && token.type_ != tokenEndOfStream) {
|
||||||
addError("Extra non-whitespace after JSON value.", token);
|
addError("Extra non-whitespace after JSON value.", token);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -1107,15 +1090,15 @@ bool OurReader::parse(const char* beginDoc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::readValue() {
|
bool OurReader::readValue() {
|
||||||
if (stackDepth_ >= features_.stackLimit_) throw std::runtime_error("Exceeded stackLimit in readValue().");
|
// To preserve the old behaviour we cast size_t to int.
|
||||||
++stackDepth_;
|
if (static_cast<int>(nodes_.size()) > features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
|
||||||
Token token;
|
Token token;
|
||||||
skipCommentTokens(token);
|
skipCommentTokens(token);
|
||||||
bool successful = true;
|
bool successful = true;
|
||||||
|
|
||||||
if (collectComments_ && !commentsBefore_.empty()) {
|
if (collectComments_ && !commentsBefore_.empty()) {
|
||||||
currentValue().setComment(commentsBefore_, commentBefore);
|
currentValue().setComment(commentsBefore_, commentBefore);
|
||||||
commentsBefore_ = "";
|
commentsBefore_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (token.type_) {
|
switch (token.type_) {
|
||||||
@@ -1157,6 +1140,30 @@ bool OurReader::readValue() {
|
|||||||
currentValue().setOffsetLimit(token.end_ - begin_);
|
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case tokenNaN:
|
||||||
|
{
|
||||||
|
Value v(std::numeric_limits<double>::quiet_NaN());
|
||||||
|
currentValue().swapPayload(v);
|
||||||
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
|
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tokenPosInf:
|
||||||
|
{
|
||||||
|
Value v(std::numeric_limits<double>::infinity());
|
||||||
|
currentValue().swapPayload(v);
|
||||||
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
|
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case tokenNegInf:
|
||||||
|
{
|
||||||
|
Value v(-std::numeric_limits<double>::infinity());
|
||||||
|
currentValue().swapPayload(v);
|
||||||
|
currentValue().setOffsetStart(token.start_ - begin_);
|
||||||
|
currentValue().setOffsetLimit(token.end_ - begin_);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case tokenArraySeparator:
|
case tokenArraySeparator:
|
||||||
case tokenObjectEnd:
|
case tokenObjectEnd:
|
||||||
case tokenArrayEnd:
|
case tokenArrayEnd:
|
||||||
@@ -1181,7 +1188,6 @@ bool OurReader::readValue() {
|
|||||||
lastValue_ = ¤tValue();
|
lastValue_ = ¤tValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
--stackDepth_;
|
|
||||||
return successful;
|
return successful;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1237,9 +1243,16 @@ bool OurReader::readToken(Token& token) {
|
|||||||
case '7':
|
case '7':
|
||||||
case '8':
|
case '8':
|
||||||
case '9':
|
case '9':
|
||||||
case '-':
|
|
||||||
token.type_ = tokenNumber;
|
token.type_ = tokenNumber;
|
||||||
readNumber();
|
readNumber(false);
|
||||||
|
break;
|
||||||
|
case '-':
|
||||||
|
if (readNumber(true)) {
|
||||||
|
token.type_ = tokenNumber;
|
||||||
|
} else {
|
||||||
|
token.type_ = tokenNegInf;
|
||||||
|
ok = features_.allowSpecialFloats_ && match("nfinity", 7);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
token.type_ = tokenTrue;
|
token.type_ = tokenTrue;
|
||||||
@@ -1253,6 +1266,22 @@ bool OurReader::readToken(Token& token) {
|
|||||||
token.type_ = tokenNull;
|
token.type_ = tokenNull;
|
||||||
ok = match("ull", 3);
|
ok = match("ull", 3);
|
||||||
break;
|
break;
|
||||||
|
case 'N':
|
||||||
|
if (features_.allowSpecialFloats_) {
|
||||||
|
token.type_ = tokenNaN;
|
||||||
|
ok = match("aN", 2);
|
||||||
|
} else {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'I':
|
||||||
|
if (features_.allowSpecialFloats_) {
|
||||||
|
token.type_ = tokenPosInf;
|
||||||
|
ok = match("nfinity", 7);
|
||||||
|
} else {
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
token.type_ = tokenArraySeparator;
|
token.type_ = tokenArraySeparator;
|
||||||
break;
|
break;
|
||||||
@@ -1319,7 +1348,7 @@ bool OurReader::readComment() {
|
|||||||
void
|
void
|
||||||
OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
|
OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
|
||||||
assert(collectComments_);
|
assert(collectComments_);
|
||||||
const std::string& normalized = normalizeEOL(begin, end);
|
const JSONCPP_STRING& normalized = normalizeEOL(begin, end);
|
||||||
if (placement == commentAfterOnSameLine) {
|
if (placement == commentAfterOnSameLine) {
|
||||||
assert(lastValue_ != 0);
|
assert(lastValue_ != 0);
|
||||||
lastValue_->setComment(normalized, placement);
|
lastValue_->setComment(normalized, placement);
|
||||||
@@ -1329,7 +1358,7 @@ OurReader::addComment(Location begin, Location end, CommentPlacement placement)
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::readCStyleComment() {
|
bool OurReader::readCStyleComment() {
|
||||||
while (current_ != end_) {
|
while ((current_ + 1) < end_) {
|
||||||
Char c = getNextChar();
|
Char c = getNextChar();
|
||||||
if (c == '*' && *current_ == '/')
|
if (c == '*' && *current_ == '/')
|
||||||
break;
|
break;
|
||||||
@@ -1353,26 +1382,31 @@ bool OurReader::readCppStyleComment() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OurReader::readNumber() {
|
bool OurReader::readNumber(bool checkInf) {
|
||||||
const char *p = current_;
|
const char *p = current_;
|
||||||
|
if (checkInf && p != end_ && *p == 'I') {
|
||||||
|
current_ = ++p;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
char c = '0'; // stopgap for already consumed character
|
char c = '0'; // stopgap for already consumed character
|
||||||
// integral part
|
// integral part
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
// fractional part
|
// fractional part
|
||||||
if (c == '.') {
|
if (c == '.') {
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
}
|
}
|
||||||
// exponential part
|
// exponential part
|
||||||
if (c == 'e' || c == 'E') {
|
if (c == 'e' || c == 'E') {
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
if (c == '+' || c == '-')
|
if (c == '+' || c == '-')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
while (c >= '0' && c <= '9')
|
while (c >= '0' && c <= '9')
|
||||||
c = (current_ = p) < end_ ? *p++ : 0;
|
c = (current_ = p) < end_ ? *p++ : '\0';
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
bool OurReader::readString() {
|
bool OurReader::readString() {
|
||||||
Char c = 0;
|
Char c = 0;
|
||||||
@@ -1401,7 +1435,7 @@ bool OurReader::readStringSingleQuote() {
|
|||||||
|
|
||||||
bool OurReader::readObject(Token& tokenStart) {
|
bool OurReader::readObject(Token& tokenStart) {
|
||||||
Token tokenName;
|
Token tokenName;
|
||||||
std::string name;
|
JSONCPP_STRING name;
|
||||||
Value init(objectValue);
|
Value init(objectValue);
|
||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
@@ -1413,7 +1447,7 @@ bool OurReader::readObject(Token& tokenStart) {
|
|||||||
break;
|
break;
|
||||||
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
|
||||||
return true;
|
return true;
|
||||||
name = "";
|
name.clear();
|
||||||
if (tokenName.type_ == tokenString) {
|
if (tokenName.type_ == tokenString) {
|
||||||
if (!decodeString(tokenName, name))
|
if (!decodeString(tokenName, name))
|
||||||
return recoverFromError(tokenObjectEnd);
|
return recoverFromError(tokenObjectEnd);
|
||||||
@@ -1431,9 +1465,9 @@ bool OurReader::readObject(Token& tokenStart) {
|
|||||||
return addErrorAndRecover(
|
return addErrorAndRecover(
|
||||||
"Missing ':' after object member name", colon, tokenObjectEnd);
|
"Missing ':' after object member name", colon, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
if (name.length() >= (1U<<30)) throw std::runtime_error("keylength >= 2^30");
|
if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
|
||||||
if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
|
if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
|
||||||
std::string msg = "Duplicate key: '" + name + "'";
|
JSONCPP_STRING msg = "Duplicate key: '" + name + "'";
|
||||||
return addErrorAndRecover(
|
return addErrorAndRecover(
|
||||||
msg, tokenName, tokenObjectEnd);
|
msg, tokenName, tokenObjectEnd);
|
||||||
}
|
}
|
||||||
@@ -1466,7 +1500,7 @@ bool OurReader::readArray(Token& tokenStart) {
|
|||||||
currentValue().swapPayload(init);
|
currentValue().swapPayload(init);
|
||||||
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
currentValue().setOffsetStart(tokenStart.start_ - begin_);
|
||||||
skipSpaces();
|
skipSpaces();
|
||||||
if (*current_ == ']') // empty array
|
if (current_ != end_ && *current_ == ']') // empty array
|
||||||
{
|
{
|
||||||
Token endArray;
|
Token endArray;
|
||||||
readToken(endArray);
|
readToken(endArray);
|
||||||
@@ -1527,7 +1561,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
|
|||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
if (c < '0' || c > '9')
|
if (c < '0' || c > '9')
|
||||||
return decodeDouble(token, decoded);
|
return decodeDouble(token, decoded);
|
||||||
Value::UInt digit(c - '0');
|
Value::UInt digit(static_cast<Value::UInt>(c - '0'));
|
||||||
if (value >= threshold) {
|
if (value >= threshold) {
|
||||||
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
// We've hit or exceeded the max value divided by 10 (rounded down). If
|
||||||
// a) we've only just touched the limit, b) this is the last digit, and
|
// a) we've only just touched the limit, b) this is the last digit, and
|
||||||
@@ -1563,12 +1597,13 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
double value = 0;
|
double value = 0;
|
||||||
const int bufferSize = 32;
|
const int bufferSize = 32;
|
||||||
int count;
|
int count;
|
||||||
int length = int(token.end_ - token.start_);
|
ptrdiff_t const length = token.end_ - token.start_;
|
||||||
|
|
||||||
// Sanity check to avoid buffer overflow exploits.
|
// Sanity check to avoid buffer overflow exploits.
|
||||||
if (length < 0) {
|
if (length < 0) {
|
||||||
return addError("Unable to parse token length", token);
|
return addError("Unable to parse token length", token);
|
||||||
}
|
}
|
||||||
|
size_t const ulength = static_cast<size_t>(length);
|
||||||
|
|
||||||
// Avoid using a string constant for the format control string given to
|
// Avoid using a string constant for the format control string given to
|
||||||
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
|
// sscanf, as this can cause hard to debug crashes on OS X. See here for more
|
||||||
@@ -1579,16 +1614,17 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
|
|
||||||
if (length <= bufferSize) {
|
if (length <= bufferSize) {
|
||||||
Char buffer[bufferSize + 1];
|
Char buffer[bufferSize + 1];
|
||||||
memcpy(buffer, token.start_, length);
|
memcpy(buffer, token.start_, ulength);
|
||||||
buffer[length] = 0;
|
buffer[length] = 0;
|
||||||
|
fixNumericLocaleInput(buffer, buffer + length);
|
||||||
count = sscanf(buffer, format, &value);
|
count = sscanf(buffer, format, &value);
|
||||||
} else {
|
} else {
|
||||||
std::string buffer(token.start_, token.end_);
|
JSONCPP_STRING buffer(token.start_, token.end_);
|
||||||
count = sscanf(buffer.c_str(), format, &value);
|
count = sscanf(buffer.c_str(), format, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count != 1)
|
if (count != 1)
|
||||||
return addError("'" + std::string(token.start_, token.end_) +
|
return addError("'" + JSONCPP_STRING(token.start_, token.end_) +
|
||||||
"' is not a number.",
|
"' is not a number.",
|
||||||
token);
|
token);
|
||||||
decoded = value;
|
decoded = value;
|
||||||
@@ -1596,7 +1632,7 @@ bool OurReader::decodeDouble(Token& token, Value& decoded) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::decodeString(Token& token) {
|
bool OurReader::decodeString(Token& token) {
|
||||||
std::string decoded_string;
|
JSONCPP_STRING decoded_string;
|
||||||
if (!decodeString(token, decoded_string))
|
if (!decodeString(token, decoded_string))
|
||||||
return false;
|
return false;
|
||||||
Value decoded(decoded_string);
|
Value decoded(decoded_string);
|
||||||
@@ -1606,8 +1642,8 @@ bool OurReader::decodeString(Token& token) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::decodeString(Token& token, std::string& decoded) {
|
bool OurReader::decodeString(Token& token, JSONCPP_STRING& decoded) {
|
||||||
decoded.reserve(token.end_ - token.start_ - 2);
|
decoded.reserve(static_cast<size_t>(token.end_ - token.start_ - 2));
|
||||||
Location current = token.start_ + 1; // skip '"'
|
Location current = token.start_ + 1; // skip '"'
|
||||||
Location end = token.end_ - 1; // do not include '"'
|
Location end = token.end_ - 1; // do not include '"'
|
||||||
while (current != end) {
|
while (current != end) {
|
||||||
@@ -1691,13 +1727,13 @@ bool OurReader::decodeUnicodeCodePoint(Token& token,
|
|||||||
bool OurReader::decodeUnicodeEscapeSequence(Token& token,
|
bool OurReader::decodeUnicodeEscapeSequence(Token& token,
|
||||||
Location& current,
|
Location& current,
|
||||||
Location end,
|
Location end,
|
||||||
unsigned int& unicode) {
|
unsigned int& ret_unicode) {
|
||||||
if (end - current < 4)
|
if (end - current < 4)
|
||||||
return addError(
|
return addError(
|
||||||
"Bad unicode escape sequence in string: four digits expected.",
|
"Bad unicode escape sequence in string: four digits expected.",
|
||||||
token,
|
token,
|
||||||
current);
|
current);
|
||||||
unicode = 0;
|
int unicode = 0;
|
||||||
for (int index = 0; index < 4; ++index) {
|
for (int index = 0; index < 4; ++index) {
|
||||||
Char c = *current++;
|
Char c = *current++;
|
||||||
unicode *= 16;
|
unicode *= 16;
|
||||||
@@ -1713,11 +1749,12 @@ bool OurReader::decodeUnicodeEscapeSequence(Token& token,
|
|||||||
token,
|
token,
|
||||||
current);
|
current);
|
||||||
}
|
}
|
||||||
|
ret_unicode = static_cast<unsigned int>(unicode);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
OurReader::addError(const std::string& message, Token& token, Location extra) {
|
OurReader::addError(const JSONCPP_STRING& message, Token& token, Location extra) {
|
||||||
ErrorInfo info;
|
ErrorInfo info;
|
||||||
info.token_ = token;
|
info.token_ = token;
|
||||||
info.message_ = message;
|
info.message_ = message;
|
||||||
@@ -1727,7 +1764,7 @@ OurReader::addError(const std::string& message, Token& token, Location extra) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::recoverFromError(TokenType skipUntilToken) {
|
bool OurReader::recoverFromError(TokenType skipUntilToken) {
|
||||||
int errorCount = int(errors_.size());
|
size_t errorCount = errors_.size();
|
||||||
Token skip;
|
Token skip;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!readToken(skip))
|
if (!readToken(skip))
|
||||||
@@ -1739,7 +1776,7 @@ bool OurReader::recoverFromError(TokenType skipUntilToken) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::addErrorAndRecover(const std::string& message,
|
bool OurReader::addErrorAndRecover(const JSONCPP_STRING& message,
|
||||||
Token& token,
|
Token& token,
|
||||||
TokenType skipUntilToken) {
|
TokenType skipUntilToken) {
|
||||||
addError(message, token);
|
addError(message, token);
|
||||||
@@ -1777,24 +1814,16 @@ void OurReader::getLocationLineAndColumn(Location location,
|
|||||||
++line;
|
++line;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OurReader::getLocationLineAndColumn(Location location) const {
|
JSONCPP_STRING OurReader::getLocationLineAndColumn(Location location) const {
|
||||||
int line, column;
|
int line, column;
|
||||||
getLocationLineAndColumn(location, line, column);
|
getLocationLineAndColumn(location, line, column);
|
||||||
char buffer[18 + 16 + 16 + 1];
|
char buffer[18 + 16 + 16 + 1];
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__)
|
|
||||||
#if defined(WINCE)
|
|
||||||
_snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
|
||||||
#else
|
|
||||||
sprintf_s(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
|
||||||
#endif
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string OurReader::getFormattedErrorMessages() const {
|
JSONCPP_STRING OurReader::getFormattedErrorMessages() const {
|
||||||
std::string formattedMessage;
|
JSONCPP_STRING formattedMessage;
|
||||||
for (Errors::const_iterator itError = errors_.begin();
|
for (Errors::const_iterator itError = errors_.begin();
|
||||||
itError != errors_.end();
|
itError != errors_.end();
|
||||||
++itError) {
|
++itError) {
|
||||||
@@ -1824,8 +1853,8 @@ std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
|
|||||||
return allErrors;
|
return allErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::pushError(const Value& value, const std::string& message) {
|
bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message) {
|
||||||
size_t length = end_ - begin_;
|
ptrdiff_t length = end_ - begin_;
|
||||||
if(value.getOffsetStart() > length
|
if(value.getOffsetStart() > length
|
||||||
|| value.getOffsetLimit() > length)
|
|| value.getOffsetLimit() > length)
|
||||||
return false;
|
return false;
|
||||||
@@ -1841,8 +1870,8 @@ bool OurReader::pushError(const Value& value, const std::string& message) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
|
bool OurReader::pushError(const Value& value, const JSONCPP_STRING& message, const Value& extra) {
|
||||||
size_t length = end_ - begin_;
|
ptrdiff_t length = end_ - begin_;
|
||||||
if(value.getOffsetStart() > length
|
if(value.getOffsetStart() > length
|
||||||
|| value.getOffsetLimit() > length
|
|| value.getOffsetLimit() > length
|
||||||
|| extra.getOffsetLimit() > length)
|
|| extra.getOffsetLimit() > length)
|
||||||
@@ -1874,9 +1903,9 @@ public:
|
|||||||
: collectComments_(collectComments)
|
: collectComments_(collectComments)
|
||||||
, reader_(features)
|
, reader_(features)
|
||||||
{}
|
{}
|
||||||
virtual bool parse(
|
bool parse(
|
||||||
char const* beginDoc, char const* endDoc,
|
char const* beginDoc, char const* endDoc,
|
||||||
Value* root, std::string* errs) {
|
Value* root, JSONCPP_STRING* errs) JSONCPP_OVERRIDE {
|
||||||
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
|
||||||
if (errs) {
|
if (errs) {
|
||||||
*errs = reader_.getFormattedErrorMessages();
|
*errs = reader_.getFormattedErrorMessages();
|
||||||
@@ -1903,9 +1932,10 @@ CharReader* CharReaderBuilder::newCharReader() const
|
|||||||
features.stackLimit_ = settings_["stackLimit"].asInt();
|
features.stackLimit_ = settings_["stackLimit"].asInt();
|
||||||
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();
|
||||||
return new OurCharReader(collectComments, features);
|
return new OurCharReader(collectComments, features);
|
||||||
}
|
}
|
||||||
static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
static void getValidReaderKeys(std::set<JSONCPP_STRING>* valid_keys)
|
||||||
{
|
{
|
||||||
valid_keys->clear();
|
valid_keys->clear();
|
||||||
valid_keys->insert("collectComments");
|
valid_keys->insert("collectComments");
|
||||||
@@ -1917,25 +1947,26 @@ static void getValidReaderKeys(std::set<std::string>* valid_keys)
|
|||||||
valid_keys->insert("stackLimit");
|
valid_keys->insert("stackLimit");
|
||||||
valid_keys->insert("failIfExtra");
|
valid_keys->insert("failIfExtra");
|
||||||
valid_keys->insert("rejectDupKeys");
|
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;
|
Json::Value my_invalid;
|
||||||
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
||||||
Json::Value& inv = *invalid;
|
Json::Value& inv = *invalid;
|
||||||
std::set<std::string> valid_keys;
|
std::set<JSONCPP_STRING> valid_keys;
|
||||||
getValidReaderKeys(&valid_keys);
|
getValidReaderKeys(&valid_keys);
|
||||||
Value::Members keys = settings_.getMemberNames();
|
Value::Members keys = settings_.getMemberNames();
|
||||||
size_t n = keys.size();
|
size_t n = keys.size();
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
std::string const& key = keys[i];
|
JSONCPP_STRING const& key = keys[i];
|
||||||
if (valid_keys.find(key) == valid_keys.end()) {
|
if (valid_keys.find(key) == valid_keys.end()) {
|
||||||
inv[key] = settings_[key];
|
inv[key] = settings_[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0u == inv.size();
|
return 0u == inv.size();
|
||||||
}
|
}
|
||||||
Value& CharReaderBuilder::operator[](std::string key)
|
Value& CharReaderBuilder::operator[](JSONCPP_STRING key)
|
||||||
{
|
{
|
||||||
return settings_[key];
|
return settings_[key];
|
||||||
}
|
}
|
||||||
@@ -1948,8 +1979,10 @@ void CharReaderBuilder::strictMode(Json::Value* settings)
|
|||||||
(*settings)["allowDroppedNullPlaceholders"] = false;
|
(*settings)["allowDroppedNullPlaceholders"] = false;
|
||||||
(*settings)["allowNumericKeys"] = false;
|
(*settings)["allowNumericKeys"] = false;
|
||||||
(*settings)["allowSingleQuotes"] = false;
|
(*settings)["allowSingleQuotes"] = false;
|
||||||
|
(*settings)["stackLimit"] = 1000;
|
||||||
(*settings)["failIfExtra"] = true;
|
(*settings)["failIfExtra"] = true;
|
||||||
(*settings)["rejectDupKeys"] = true;
|
(*settings)["rejectDupKeys"] = true;
|
||||||
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
//! [CharReaderBuilderStrictMode]
|
//! [CharReaderBuilderStrictMode]
|
||||||
}
|
}
|
||||||
// static
|
// static
|
||||||
@@ -1965,6 +1998,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
|
|||||||
(*settings)["stackLimit"] = 1000;
|
(*settings)["stackLimit"] = 1000;
|
||||||
(*settings)["failIfExtra"] = false;
|
(*settings)["failIfExtra"] = false;
|
||||||
(*settings)["rejectDupKeys"] = false;
|
(*settings)["rejectDupKeys"] = false;
|
||||||
|
(*settings)["allowSpecialFloats"] = false;
|
||||||
//! [CharReaderBuilderDefaults]
|
//! [CharReaderBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1972,12 +2006,12 @@ void CharReaderBuilder::setDefaults(Json::Value* settings)
|
|||||||
// global functions
|
// global functions
|
||||||
|
|
||||||
bool parseFromStream(
|
bool parseFromStream(
|
||||||
CharReader::Factory const& fact, std::istream& sin,
|
CharReader::Factory const& fact, JSONCPP_ISTREAM& sin,
|
||||||
Value* root, std::string* errs)
|
Value* root, JSONCPP_STRING* errs)
|
||||||
{
|
{
|
||||||
std::ostringstream ssin;
|
JSONCPP_OSTRINGSTREAM ssin;
|
||||||
ssin << sin.rdbuf();
|
ssin << sin.rdbuf();
|
||||||
std::string doc = ssin.str();
|
JSONCPP_STRING doc = 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.
|
||||||
@@ -1985,16 +2019,16 @@ bool parseFromStream(
|
|||||||
return reader->parse(begin, end, root, errs);
|
return reader->parse(begin, end, root, errs);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::istream& operator>>(std::istream& sin, Value& root) {
|
JSONCPP_ISTREAM& operator>>(JSONCPP_ISTREAM& sin, Value& root) {
|
||||||
CharReaderBuilder b;
|
CharReaderBuilder b;
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = parseFromStream(b, sin, &root, &errs);
|
bool ok = parseFromStream(b, sin, &root, &errs);
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Error from reader: %s",
|
"Error from reader: %s",
|
||||||
errs.c_str());
|
errs.c_str());
|
||||||
|
|
||||||
JSON_FAIL_MESSAGE("reader error");
|
throwRuntimeError(errs);
|
||||||
}
|
}
|
||||||
return sin;
|
return sin;
|
||||||
}
|
}
|
||||||
|
@@ -6,6 +6,16 @@
|
|||||||
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
|
||||||
|
|
||||||
|
// Also support old flag NO_LOCALE_SUPPORT
|
||||||
|
#ifdef NO_LOCALE_SUPPORT
|
||||||
|
#define JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
#include <clocale>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* This header provides common string manipulation support, such as UTF-8,
|
/* This header provides common string manipulation support, such as UTF-8,
|
||||||
* portable conversion from/to string...
|
* portable conversion from/to string...
|
||||||
*
|
*
|
||||||
@@ -13,10 +23,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
static char getDecimalPoint() {
|
||||||
|
#ifdef JSONCPP_NO_LOCALE_SUPPORT
|
||||||
|
return '\0';
|
||||||
|
#else
|
||||||
|
struct lconv* lc = localeconv();
|
||||||
|
return lc ? *(lc->decimal_point) : '\0';
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/// Converts a unicode code-point to UTF-8.
|
/// Converts a unicode code-point to UTF-8.
|
||||||
static inline std::string codePointToUTF8(unsigned int cp) {
|
static inline JSONCPP_STRING codePointToUTF8(unsigned int cp) {
|
||||||
std::string result;
|
JSONCPP_STRING result;
|
||||||
|
|
||||||
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
// based on description from http://en.wikipedia.org/wiki/UTF-8
|
||||||
|
|
||||||
@@ -30,8 +48,8 @@ static inline std::string codePointToUTF8(unsigned int cp) {
|
|||||||
} else if (cp <= 0xFFFF) {
|
} else if (cp <= 0xFFFF) {
|
||||||
result.resize(3);
|
result.resize(3);
|
||||||
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
result[2] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
result[1] = 0x80 | static_cast<char>((0x3f & (cp >> 6)));
|
result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
|
||||||
result[0] = 0xE0 | static_cast<char>((0xf & (cp >> 12)));
|
result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
|
||||||
} else if (cp <= 0x10FFFF) {
|
} else if (cp <= 0x10FFFF) {
|
||||||
result.resize(4);
|
result.resize(4);
|
||||||
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
result[3] = static_cast<char>(0x80 | (0x3f & cp));
|
||||||
@@ -43,7 +61,7 @@ static inline std::string codePointToUTF8(unsigned int cp) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if ch is a control character (in range [0,32[).
|
/// Returns true if ch is a control character (in range [1,31]).
|
||||||
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -63,7 +81,7 @@ typedef char UIntToStringBuffer[uintToStringBufferSize];
|
|||||||
static inline void uintToString(LargestUInt value, char*& current) {
|
static inline void uintToString(LargestUInt value, char*& current) {
|
||||||
*--current = 0;
|
*--current = 0;
|
||||||
do {
|
do {
|
||||||
*--current = char(value % 10) + '0';
|
*--current = static_cast<char>(value % 10U + static_cast<unsigned>('0'));
|
||||||
value /= 10;
|
value /= 10;
|
||||||
} while (value != 0);
|
} while (value != 0);
|
||||||
}
|
}
|
||||||
@@ -82,6 +100,18 @@ static inline void fixNumericLocale(char* begin, char* end) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void fixNumericLocaleInput(char* begin, char* end) {
|
||||||
|
char decimalPoint = getDecimalPoint();
|
||||||
|
if (decimalPoint != '\0' && decimalPoint != '.') {
|
||||||
|
while (begin < end) {
|
||||||
|
if (*begin == '.') {
|
||||||
|
*begin = decimalPoint;
|
||||||
|
}
|
||||||
|
++begin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Json {
|
} // namespace Json {
|
||||||
|
|
||||||
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
|
||||||
|
@@ -31,10 +31,22 @@ namespace Json {
|
|||||||
#else
|
#else
|
||||||
#define ALIGNAS(byte_alignment)
|
#define ALIGNAS(byte_alignment)
|
||||||
#endif
|
#endif
|
||||||
static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
|
//static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
|
||||||
const unsigned char& kNullRef = kNull[0];
|
//const unsigned char& kNullRef = kNull[0];
|
||||||
const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
|
//const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
|
||||||
const Value& Value::nullRef = null;
|
//const Value& Value::nullRef = null;
|
||||||
|
|
||||||
|
// static
|
||||||
|
Value const& Value::nullSingleton()
|
||||||
|
{
|
||||||
|
static Value const nullStatic;
|
||||||
|
return nullStatic;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for backwards compatibility, we'll leave these global references around, but DO NOT
|
||||||
|
// use them in JSONCPP library code any more!
|
||||||
|
Value const& Value::null = Value::nullSingleton();
|
||||||
|
Value const& Value::nullRef = Value::nullSingleton();
|
||||||
|
|
||||||
const Int Value::minInt = Int(~(UInt(-1) / 2));
|
const Int Value::minInt = Int(~(UInt(-1) / 2));
|
||||||
const Int Value::maxInt = Int(UInt(-1) / 2);
|
const Int Value::maxInt = Int(UInt(-1) / 2);
|
||||||
@@ -55,11 +67,14 @@ const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
|
|||||||
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
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) {
|
||||||
|
// The casts can lose precision, but we are looking only for
|
||||||
|
// an approximate range. Might fail on edge cases though. ~cdunn
|
||||||
|
//return d >= static_cast<double>(min) && d <= static_cast<double>(max);
|
||||||
return d >= min && d <= max;
|
return d >= min && d <= max;
|
||||||
}
|
}
|
||||||
#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) {
|
||||||
return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
|
return static_cast<double>(Int64(value / 2)) * 2.0 + static_cast<double>(Int64(value & 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T> static inline double integerToDouble(T value) {
|
template <typename T> static inline double integerToDouble(T value) {
|
||||||
@@ -80,16 +95,19 @@ static inline bool InRange(double d, T min, U max) {
|
|||||||
* @return Pointer on the duplicate instance of string.
|
* @return Pointer on the duplicate instance of string.
|
||||||
*/
|
*/
|
||||||
static inline char* duplicateStringValue(const char* value,
|
static inline char* duplicateStringValue(const char* value,
|
||||||
size_t length) {
|
size_t length)
|
||||||
|
{
|
||||||
// Avoid an integer overflow in the call to malloc below by limiting length
|
// Avoid an integer overflow in the call to malloc below by limiting length
|
||||||
// to a sane value.
|
// to a sane value.
|
||||||
if (length >= (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));
|
char* newString = static_cast<char*>(malloc(length + 1));
|
||||||
JSON_ASSERT_MESSAGE(newString != 0,
|
if (newString == NULL) {
|
||||||
|
throwRuntimeError(
|
||||||
"in Json::Value::duplicateStringValue(): "
|
"in Json::Value::duplicateStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
|
}
|
||||||
memcpy(newString, value, length);
|
memcpy(newString, value, length);
|
||||||
newString[length] = 0;
|
newString[length] = 0;
|
||||||
return newString;
|
return newString;
|
||||||
@@ -103,14 +121,16 @@ static inline char* duplicateAndPrefixStringValue(
|
|||||||
{
|
{
|
||||||
// Avoid an integer overflow in the call to malloc below by limiting length
|
// Avoid an integer overflow in the call to malloc below by limiting length
|
||||||
// to a sane value.
|
// to a sane value.
|
||||||
JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
|
JSON_ASSERT_MESSAGE(length <= static_cast<unsigned>(Value::maxInt) - sizeof(unsigned) - 1U,
|
||||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"length too big for prefixing");
|
"length too big for prefixing");
|
||||||
unsigned actualLength = length + sizeof(unsigned) + 1U;
|
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
|
||||||
char* newString = static_cast<char*>(malloc(actualLength));
|
char* newString = static_cast<char*>(malloc(actualLength));
|
||||||
JSON_ASSERT_MESSAGE(newString != 0,
|
if (newString == 0) {
|
||||||
|
throwRuntimeError(
|
||||||
"in Json::Value::duplicateAndPrefixStringValue(): "
|
"in Json::Value::duplicateAndPrefixStringValue(): "
|
||||||
"Failed to allocate string value buffer");
|
"Failed to allocate string value buffer");
|
||||||
|
}
|
||||||
*reinterpret_cast<unsigned*>(newString) = length;
|
*reinterpret_cast<unsigned*>(newString) = length;
|
||||||
memcpy(newString + sizeof(unsigned), value, length);
|
memcpy(newString + sizeof(unsigned), value, length);
|
||||||
newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
|
newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
|
||||||
@@ -121,7 +141,7 @@ inline static void decodePrefixedString(
|
|||||||
unsigned* length, char const** value)
|
unsigned* length, char const** value)
|
||||||
{
|
{
|
||||||
if (!isPrefixed) {
|
if (!isPrefixed) {
|
||||||
*length = strlen(prefixed);
|
*length = static_cast<unsigned>(strlen(prefixed));
|
||||||
*value = prefixed;
|
*value = prefixed;
|
||||||
} else {
|
} else {
|
||||||
*length = *reinterpret_cast<unsigned const*>(prefixed);
|
*length = *reinterpret_cast<unsigned const*>(prefixed);
|
||||||
@@ -130,7 +150,29 @@ inline static void decodePrefixedString(
|
|||||||
}
|
}
|
||||||
/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
|
/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
|
||||||
*/
|
*/
|
||||||
static inline void releaseStringValue(char* value) { free(value); }
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
static inline void releasePrefixedStringValue(char* value) {
|
||||||
|
unsigned length = 0;
|
||||||
|
char const* valueDecoded;
|
||||||
|
decodePrefixedString(true, value, &length, &valueDecoded);
|
||||||
|
size_t const size = sizeof(unsigned) + length + 1U;
|
||||||
|
memset(value, 0, size);
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
static inline void releaseStringValue(char* value, unsigned length) {
|
||||||
|
// length==0 => we allocated the strings memory
|
||||||
|
size_t size = (length==0) ? strlen(value) : length;
|
||||||
|
memset(value, 0, size);
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
#else // !JSONCPP_USING_SECURE_MEMORY
|
||||||
|
static inline void releasePrefixedStringValue(char* value) {
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
static inline void releaseStringValue(char* value, unsigned) {
|
||||||
|
free(value);
|
||||||
|
}
|
||||||
|
#endif // JSONCPP_USING_SECURE_MEMORY
|
||||||
|
|
||||||
} // namespace Json
|
} // namespace Json
|
||||||
|
|
||||||
@@ -148,6 +190,30 @@ static inline void releaseStringValue(char* value) { free(value); }
|
|||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
|
Exception::Exception(JSONCPP_STRING const& msg)
|
||||||
|
: msg_(msg)
|
||||||
|
{}
|
||||||
|
Exception::~Exception() JSONCPP_NOEXCEPT
|
||||||
|
{}
|
||||||
|
char const* Exception::what() const JSONCPP_NOEXCEPT
|
||||||
|
{
|
||||||
|
return msg_.c_str();
|
||||||
|
}
|
||||||
|
RuntimeError::RuntimeError(JSONCPP_STRING const& msg)
|
||||||
|
: Exception(msg)
|
||||||
|
{}
|
||||||
|
LogicError::LogicError(JSONCPP_STRING const& msg)
|
||||||
|
: Exception(msg)
|
||||||
|
{}
|
||||||
|
JSONCPP_NORETURN void throwRuntimeError(JSONCPP_STRING const& msg)
|
||||||
|
{
|
||||||
|
throw RuntimeError(msg);
|
||||||
|
}
|
||||||
|
JSONCPP_NORETURN void throwLogicError(JSONCPP_STRING const& msg)
|
||||||
|
{
|
||||||
|
throw LogicError(msg);
|
||||||
|
}
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -156,16 +222,17 @@ namespace Json {
|
|||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Value::CommentInfo::CommentInfo() : comment_(0) {}
|
Value::CommentInfo::CommentInfo() : comment_(0)
|
||||||
|
{}
|
||||||
|
|
||||||
Value::CommentInfo::~CommentInfo() {
|
Value::CommentInfo::~CommentInfo() {
|
||||||
if (comment_)
|
if (comment_)
|
||||||
releaseStringValue(comment_);
|
releaseStringValue(comment_, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::CommentInfo::setComment(const char* text, size_t len) {
|
void Value::CommentInfo::setComment(const char* text, size_t len) {
|
||||||
if (comment_) {
|
if (comment_) {
|
||||||
releaseStringValue(comment_);
|
releaseStringValue(comment_, 0u);
|
||||||
comment_ = 0;
|
comment_ = 0;
|
||||||
}
|
}
|
||||||
JSON_ASSERT(text != 0);
|
JSON_ASSERT(text != 0);
|
||||||
@@ -187,31 +254,37 @@ void Value::CommentInfo::setComment(const char* text, size_t len) {
|
|||||||
// Notes: policy_ indicates if the string was allocated when
|
// Notes: policy_ indicates if the string was allocated when
|
||||||
// a string is stored.
|
// a string is stored.
|
||||||
|
|
||||||
Value::CZString::CZString(ArrayIndex index) : cstr_(0), index_(index) {}
|
Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
|
||||||
|
|
||||||
Value::CZString::CZString(char const* str, unsigned length, DuplicationPolicy allocate)
|
Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
|
||||||
: cstr_(str)
|
: cstr_(str) {
|
||||||
{
|
|
||||||
// allocate != duplicate
|
// allocate != duplicate
|
||||||
storage_.policy_ = allocate;
|
storage_.policy_ = allocate & 0x3;
|
||||||
storage_.length_ = length;
|
storage_.length_ = ulength & 0x3FFFFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::CZString::CZString(const CZString& other)
|
Value::CZString::CZString(const CZString& other) {
|
||||||
: cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
|
cstr_ = (other.storage_.policy_ != noDuplication && other.cstr_ != 0
|
||||||
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
? duplicateStringValue(other.cstr_, other.storage_.length_)
|
||||||
: other.cstr_)
|
: other.cstr_);
|
||||||
{
|
storage_.policy_ = static_cast<unsigned>(other.cstr_
|
||||||
storage_.policy_ = (other.cstr_
|
? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
|
||||||
? (other.storage_.policy_ == noDuplication
|
|
||||||
? noDuplication : duplicate)
|
? noDuplication : duplicate)
|
||||||
: other.storage_.policy_);
|
: static_cast<DuplicationPolicy>(other.storage_.policy_)) & 3U;
|
||||||
storage_.length_ = other.storage_.length_;
|
storage_.length_ = other.storage_.length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
Value::CZString::CZString(CZString&& other)
|
||||||
|
: cstr_(other.cstr_), index_(other.index_) {
|
||||||
|
other.cstr_ = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::CZString::~CZString() {
|
Value::CZString::~CZString() {
|
||||||
if (cstr_ && storage_.policy_ == duplicate)
|
if (cstr_ && storage_.policy_ == duplicate) {
|
||||||
releaseStringValue(const_cast<char*>(cstr_));
|
releaseStringValue(const_cast<char*>(cstr_), storage_.length_ + 1u); //+1 for null terminating character for sake of completeness but not actually necessary
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::CZString::swap(CZString& other) {
|
void Value::CZString::swap(CZString& other) {
|
||||||
@@ -230,7 +303,8 @@ bool Value::CZString::operator<(const CZString& other) const {
|
|||||||
// Assume both are strings.
|
// Assume both are strings.
|
||||||
unsigned this_len = this->storage_.length_;
|
unsigned this_len = this->storage_.length_;
|
||||||
unsigned other_len = other.storage_.length_;
|
unsigned other_len = other.storage_.length_;
|
||||||
unsigned min_len = std::min(this_len, other_len);
|
unsigned min_len = std::min<unsigned>(this_len, other_len);
|
||||||
|
JSON_ASSERT(this->cstr_ && other.cstr_);
|
||||||
int comp = memcmp(this->cstr_, other.cstr_, min_len);
|
int comp = memcmp(this->cstr_, other.cstr_, min_len);
|
||||||
if (comp < 0) return true;
|
if (comp < 0) return true;
|
||||||
if (comp > 0) return false;
|
if (comp > 0) return false;
|
||||||
@@ -244,6 +318,7 @@ bool Value::CZString::operator==(const CZString& other) const {
|
|||||||
unsigned this_len = this->storage_.length_;
|
unsigned this_len = this->storage_.length_;
|
||||||
unsigned other_len = other.storage_.length_;
|
unsigned other_len = other.storage_.length_;
|
||||||
if (this_len != other_len) return false;
|
if (this_len != other_len) return false;
|
||||||
|
JSON_ASSERT(this->cstr_ && other.cstr_);
|
||||||
int comp = memcmp(this->cstr_, other.cstr_, this_len);
|
int comp = memcmp(this->cstr_, other.cstr_, this_len);
|
||||||
return comp == 0;
|
return comp == 0;
|
||||||
}
|
}
|
||||||
@@ -267,9 +342,10 @@ bool Value::CZString::isStaticString() const { return storage_.policy_ == noDupl
|
|||||||
* memset( this, 0, sizeof(Value) )
|
* memset( this, 0, sizeof(Value) )
|
||||||
* This optimization is used in ValueInternalMap fast allocator.
|
* This optimization is used in ValueInternalMap fast allocator.
|
||||||
*/
|
*/
|
||||||
Value::Value(ValueType type) {
|
Value::Value(ValueType vtype) {
|
||||||
initBasic(type);
|
static char const emptyString[] = "";
|
||||||
switch (type) {
|
initBasic(vtype);
|
||||||
|
switch (vtype) {
|
||||||
case nullValue:
|
case nullValue:
|
||||||
break;
|
break;
|
||||||
case intValue:
|
case intValue:
|
||||||
@@ -280,7 +356,8 @@ Value::Value(ValueType type) {
|
|||||||
value_.real_ = 0.0;
|
value_.real_ = 0.0;
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
value_.string_ = 0;
|
// allocated_ == false, so this is safe.
|
||||||
|
value_.string_ = const_cast<char*>(static_cast<char const*>(emptyString));
|
||||||
break;
|
break;
|
||||||
case arrayValue:
|
case arrayValue:
|
||||||
case objectValue:
|
case objectValue:
|
||||||
@@ -321,6 +398,7 @@ Value::Value(double value) {
|
|||||||
|
|
||||||
Value::Value(const char* value) {
|
Value::Value(const char* value) {
|
||||||
initBasic(stringValue, true);
|
initBasic(stringValue, true);
|
||||||
|
JSON_ASSERT_MESSAGE(value != NULL, "Null Value Passed to Value Constructor");
|
||||||
value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
|
value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +408,7 @@ Value::Value(const char* beginValue, const char* endValue) {
|
|||||||
duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
|
duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value::Value(const std::string& value) {
|
Value::Value(const JSONCPP_STRING& value) {
|
||||||
initBasic(stringValue, true);
|
initBasic(stringValue, true);
|
||||||
value_.string_ =
|
value_.string_ =
|
||||||
duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
|
duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
|
||||||
@@ -397,6 +475,14 @@ Value::Value(Value const& other)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
// Move constructor
|
||||||
|
Value::Value(Value&& other) {
|
||||||
|
initBasic(nullValue);
|
||||||
|
swap(other);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Value::~Value() {
|
Value::~Value() {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case nullValue:
|
case nullValue:
|
||||||
@@ -407,7 +493,7 @@ Value::~Value() {
|
|||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
if (allocated_)
|
if (allocated_)
|
||||||
releaseStringValue(value_.string_);
|
releasePrefixedStringValue(value_.string_);
|
||||||
break;
|
break;
|
||||||
case arrayValue:
|
case arrayValue:
|
||||||
case objectValue:
|
case objectValue:
|
||||||
@@ -417,8 +503,9 @@ Value::~Value() {
|
|||||||
JSON_ASSERT_UNREACHABLE;
|
JSON_ASSERT_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comments_)
|
|
||||||
delete[] comments_;
|
delete[] comments_;
|
||||||
|
|
||||||
|
value_.uint_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& Value::operator=(Value other) {
|
Value& Value::operator=(Value other) {
|
||||||
@@ -433,7 +520,7 @@ void Value::swapPayload(Value& other) {
|
|||||||
std::swap(value_, other.value_);
|
std::swap(value_, other.value_);
|
||||||
int temp2 = allocated_;
|
int temp2 = allocated_;
|
||||||
allocated_ = other.allocated_;
|
allocated_ = other.allocated_;
|
||||||
other.allocated_ = temp2;
|
other.allocated_ = temp2 & 0x1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::swap(Value& other) {
|
void Value::swap(Value& other) {
|
||||||
@@ -480,7 +567,8 @@ bool Value::operator<(const Value& other) const {
|
|||||||
char const* other_str;
|
char const* other_str;
|
||||||
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
||||||
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
|
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
|
||||||
unsigned min_len = std::min(this_len, other_len);
|
unsigned min_len = std::min<unsigned>(this_len, other_len);
|
||||||
|
JSON_ASSERT(this_str && other_str);
|
||||||
int comp = memcmp(this_str, other_str, min_len);
|
int comp = memcmp(this_str, other_str, min_len);
|
||||||
if (comp < 0) return true;
|
if (comp < 0) return true;
|
||||||
if (comp > 0) return false;
|
if (comp > 0) return false;
|
||||||
@@ -536,6 +624,7 @@ bool Value::operator==(const Value& other) const {
|
|||||||
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
||||||
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
|
decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
|
||||||
if (this_len != other_len) return false;
|
if (this_len != other_len) return false;
|
||||||
|
JSON_ASSERT(this_str && other_str);
|
||||||
int comp = memcmp(this_str, other_str, this_len);
|
int comp = memcmp(this_str, other_str, this_len);
|
||||||
return comp == 0;
|
return comp == 0;
|
||||||
}
|
}
|
||||||
@@ -561,16 +650,28 @@ const char* Value::asCString() const {
|
|||||||
return this_str;
|
return this_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::getString(char const** str, char const** end) const {
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
unsigned Value::getCStringLength() const {
|
||||||
|
JSON_ASSERT_MESSAGE(type_ == stringValue,
|
||||||
|
"in Json::Value::asCString(): requires stringValue");
|
||||||
|
if (value_.string_ == 0) return 0;
|
||||||
|
unsigned this_len;
|
||||||
|
char const* this_str;
|
||||||
|
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
||||||
|
return this_len;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool Value::getString(char const** str, char const** cend) const {
|
||||||
if (type_ != stringValue) return false;
|
if (type_ != stringValue) return false;
|
||||||
if (value_.string_ == 0) return false;
|
if (value_.string_ == 0) return false;
|
||||||
unsigned length;
|
unsigned length;
|
||||||
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
|
decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
|
||||||
*end = *str + length;
|
*cend = *str + length;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Value::asString() const {
|
JSONCPP_STRING Value::asString() const {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case nullValue:
|
case nullValue:
|
||||||
return "";
|
return "";
|
||||||
@@ -580,7 +681,7 @@ std::string Value::asString() const {
|
|||||||
unsigned this_len;
|
unsigned this_len;
|
||||||
char const* this_str;
|
char const* this_str;
|
||||||
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
|
||||||
return std::string(this_str, this_len);
|
return JSONCPP_STRING(this_str, this_len);
|
||||||
}
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
return value_.bool_ ? "true" : "false";
|
return value_.bool_ ? "true" : "false";
|
||||||
@@ -740,7 +841,8 @@ float Value::asFloat() const {
|
|||||||
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
return static_cast<float>(value_.uint_);
|
return static_cast<float>(value_.uint_);
|
||||||
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
return integerToDouble(value_.uint_);
|
// This can fail (silently?) if the value is bigger than MAX_FLOAT.
|
||||||
|
return static_cast<float>(integerToDouble(value_.uint_));
|
||||||
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
case realValue:
|
case realValue:
|
||||||
return static_cast<float>(value_.real_);
|
return static_cast<float>(value_.real_);
|
||||||
@@ -765,7 +867,8 @@ bool Value::asBool() const {
|
|||||||
case uintValue:
|
case uintValue:
|
||||||
return value_.uint_ ? true : false;
|
return value_.uint_ ? true : false;
|
||||||
case realValue:
|
case realValue:
|
||||||
return value_.real_ ? true : false;
|
// This is kind of strange. Not recommended.
|
||||||
|
return (value_.real_ != 0.0) ? true : false;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -777,7 +880,7 @@ bool Value::isConvertibleTo(ValueType other) const {
|
|||||||
case nullValue:
|
case nullValue:
|
||||||
return (isNumeric() && asDouble() == 0.0) ||
|
return (isNumeric() && asDouble() == 0.0) ||
|
||||||
(type_ == booleanValue && value_.bool_ == false) ||
|
(type_ == booleanValue && value_.bool_ == false) ||
|
||||||
(type_ == stringValue && asString() == "") ||
|
(type_ == stringValue && asString().empty()) ||
|
||||||
(type_ == arrayValue && value_.map_->size() == 0) ||
|
(type_ == arrayValue && value_.map_->size() == 0) ||
|
||||||
(type_ == objectValue && value_.map_->size() == 0) ||
|
(type_ == objectValue && value_.map_->size() == 0) ||
|
||||||
type_ == nullValue;
|
type_ == nullValue;
|
||||||
@@ -868,7 +971,7 @@ void Value::resize(ArrayIndex newSize) {
|
|||||||
for (ArrayIndex index = newSize; index < oldSize; ++index) {
|
for (ArrayIndex index = newSize; index < oldSize; ++index) {
|
||||||
value_.map_->erase(index);
|
value_.map_->erase(index);
|
||||||
}
|
}
|
||||||
assert(size() == newSize);
|
JSON_ASSERT(size() == newSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -883,7 +986,7 @@ Value& Value::operator[](ArrayIndex index) {
|
|||||||
if (it != value_.map_->end() && (*it).first == key)
|
if (it != value_.map_->end() && (*it).first == key)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(key, nullRef);
|
ObjectValues::value_type defaultValue(key, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
@@ -900,11 +1003,11 @@ const Value& Value::operator[](ArrayIndex index) const {
|
|||||||
type_ == nullValue || type_ == arrayValue,
|
type_ == nullValue || type_ == arrayValue,
|
||||||
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
|
"in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
|
||||||
if (type_ == nullValue)
|
if (type_ == nullValue)
|
||||||
return nullRef;
|
return nullSingleton();
|
||||||
CZString key(index);
|
CZString key(index);
|
||||||
ObjectValues::const_iterator it = value_.map_->find(key);
|
ObjectValues::const_iterator it = value_.map_->find(key);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return nullRef;
|
return nullSingleton();
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -915,8 +1018,8 @@ const Value& Value::operator[](int index) const {
|
|||||||
return (*this)[ArrayIndex(index)];
|
return (*this)[ArrayIndex(index)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::initBasic(ValueType type, bool allocated) {
|
void Value::initBasic(ValueType vtype, bool allocated) {
|
||||||
type_ = type;
|
type_ = vtype;
|
||||||
allocated_ = allocated;
|
allocated_ = allocated;
|
||||||
comments_ = 0;
|
comments_ = 0;
|
||||||
start_ = 0;
|
start_ = 0;
|
||||||
@@ -938,14 +1041,14 @@ Value& Value::resolveReference(const char* key) {
|
|||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(actualKey, nullRef);
|
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
Value& value = (*it).second;
|
Value& value = (*it).second;
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @param key is not null-terminated.
|
// @param key is not null-terminated.
|
||||||
Value& Value::resolveReference(char const* key, char const* end)
|
Value& Value::resolveReference(char const* key, char const* cend)
|
||||||
{
|
{
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
type_ == nullValue || type_ == objectValue,
|
type_ == nullValue || type_ == objectValue,
|
||||||
@@ -953,12 +1056,12 @@ Value& Value::resolveReference(char const* key, char const* end)
|
|||||||
if (type_ == nullValue)
|
if (type_ == nullValue)
|
||||||
*this = Value(objectValue);
|
*this = Value(objectValue);
|
||||||
CZString actualKey(
|
CZString actualKey(
|
||||||
key, static_cast<unsigned>(end-key), CZString::duplicateOnCopy);
|
key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
|
||||||
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
|
||||||
if (it != value_.map_->end() && (*it).first == actualKey)
|
if (it != value_.map_->end() && (*it).first == actualKey)
|
||||||
return (*it).second;
|
return (*it).second;
|
||||||
|
|
||||||
ObjectValues::value_type defaultValue(actualKey, nullRef);
|
ObjectValues::value_type defaultValue(actualKey, nullSingleton());
|
||||||
it = value_.map_->insert(it, defaultValue);
|
it = value_.map_->insert(it, defaultValue);
|
||||||
Value& value = (*it).second;
|
Value& value = (*it).second;
|
||||||
return value;
|
return value;
|
||||||
@@ -966,18 +1069,18 @@ Value& Value::resolveReference(char const* key, char const* end)
|
|||||||
|
|
||||||
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
|
Value Value::get(ArrayIndex index, const Value& defaultValue) const {
|
||||||
const Value* value = &((*this)[index]);
|
const Value* value = &((*this)[index]);
|
||||||
return value == &nullRef ? defaultValue : *value;
|
return value == &nullSingleton() ? defaultValue : *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
|
bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
|
||||||
|
|
||||||
Value const* Value::find(char const* key, char const* end) const
|
Value const* Value::find(char const* key, char const* cend) const
|
||||||
{
|
{
|
||||||
JSON_ASSERT_MESSAGE(
|
JSON_ASSERT_MESSAGE(
|
||||||
type_ == nullValue || type_ == objectValue,
|
type_ == nullValue || type_ == objectValue,
|
||||||
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
|
"in Json::Value::find(key, end, found): requires objectValue or nullValue");
|
||||||
if (type_ == nullValue) return NULL;
|
if (type_ == nullValue) return NULL;
|
||||||
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
|
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
|
||||||
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
ObjectValues::const_iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end()) return NULL;
|
if (it == value_.map_->end()) return NULL;
|
||||||
return &(*it).second;
|
return &(*it).second;
|
||||||
@@ -985,13 +1088,13 @@ Value const* Value::find(char const* key, char const* end) const
|
|||||||
const Value& Value::operator[](const char* key) const
|
const Value& Value::operator[](const char* key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key, key + strlen(key));
|
Value const* found = find(key, key + strlen(key));
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
Value const& Value::operator[](std::string const& key) const
|
Value const& Value::operator[](JSONCPP_STRING const& key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key.data(), key.data() + key.length());
|
Value const* found = find(key.data(), key.data() + key.length());
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +1102,7 @@ Value& Value::operator[](const char* key) {
|
|||||||
return resolveReference(key, key + strlen(key));
|
return resolveReference(key, key + strlen(key));
|
||||||
}
|
}
|
||||||
|
|
||||||
Value& Value::operator[](const std::string& key) {
|
Value& Value::operator[](const JSONCPP_STRING& key) {
|
||||||
return resolveReference(key.data(), key.data() + key.length());
|
return resolveReference(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1014,34 +1117,34 @@ Value& Value::operator[](const CppTL::ConstString& key) {
|
|||||||
Value const& Value::operator[](CppTL::ConstString const& key) const
|
Value const& Value::operator[](CppTL::ConstString const& key) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key.c_str(), key.end_c_str());
|
Value const* found = find(key.c_str(), key.end_c_str());
|
||||||
if (!found) return nullRef;
|
if (!found) return nullSingleton();
|
||||||
return *found;
|
return *found;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
|
Value& Value::append(const Value& value) { return (*this)[size()] = value; }
|
||||||
|
|
||||||
Value Value::get(char const* key, char const* end, Value const& defaultValue) const
|
Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
|
||||||
{
|
{
|
||||||
Value const* found = find(key, end);
|
Value const* found = find(key, cend);
|
||||||
return !found ? defaultValue : *found;
|
return !found ? defaultValue : *found;
|
||||||
}
|
}
|
||||||
Value Value::get(char const* key, Value const& defaultValue) const
|
Value Value::get(char const* key, Value const& defaultValue) const
|
||||||
{
|
{
|
||||||
return get(key, key + strlen(key), defaultValue);
|
return get(key, key + strlen(key), defaultValue);
|
||||||
}
|
}
|
||||||
Value Value::get(std::string const& key, Value const& defaultValue) const
|
Value Value::get(JSONCPP_STRING const& key, Value const& defaultValue) const
|
||||||
{
|
{
|
||||||
return get(key.data(), key.data() + key.length(), defaultValue);
|
return get(key.data(), key.data() + key.length(), defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Value::removeMember(const char* key, const char* end, Value* removed)
|
bool Value::removeMember(const char* key, const char* cend, Value* removed)
|
||||||
{
|
{
|
||||||
if (type_ != objectValue) {
|
if (type_ != objectValue) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
CZString actualKey(key, static_cast<unsigned>(end-key), CZString::noDuplication);
|
CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
|
||||||
ObjectValues::iterator it = value_.map_->find(actualKey);
|
ObjectValues::iterator it = value_.map_->find(actualKey);
|
||||||
if (it == value_.map_->end())
|
if (it == value_.map_->end())
|
||||||
return false;
|
return false;
|
||||||
@@ -1053,7 +1156,7 @@ bool Value::removeMember(const char* key, Value* removed)
|
|||||||
{
|
{
|
||||||
return removeMember(key, key + strlen(key), removed);
|
return removeMember(key, key + strlen(key), removed);
|
||||||
}
|
}
|
||||||
bool Value::removeMember(std::string const& key, Value* removed)
|
bool Value::removeMember(JSONCPP_STRING const& key, Value* removed)
|
||||||
{
|
{
|
||||||
return removeMember(key.data(), key.data() + key.length(), removed);
|
return removeMember(key.data(), key.data() + key.length(), removed);
|
||||||
}
|
}
|
||||||
@@ -1062,13 +1165,13 @@ Value Value::removeMember(const char* key)
|
|||||||
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
|
JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
|
||||||
"in Json::Value::removeMember(): requires objectValue");
|
"in Json::Value::removeMember(): requires objectValue");
|
||||||
if (type_ == nullValue)
|
if (type_ == nullValue)
|
||||||
return nullRef;
|
return nullSingleton();
|
||||||
|
|
||||||
Value removed; // null
|
Value removed; // null
|
||||||
removeMember(key, key + strlen(key), &removed);
|
removeMember(key, key + strlen(key), &removed);
|
||||||
return removed; // still null if removeMember() did nothing
|
return removed; // still null if removeMember() did nothing
|
||||||
}
|
}
|
||||||
Value Value::removeMember(const std::string& key)
|
Value Value::removeMember(const JSONCPP_STRING& key)
|
||||||
{
|
{
|
||||||
return removeMember(key.c_str());
|
return removeMember(key.c_str());
|
||||||
}
|
}
|
||||||
@@ -1086,8 +1189,8 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
|
|||||||
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){
|
||||||
CZString key(i);
|
CZString keey(i);
|
||||||
(*value_.map_)[key] = (*this)[i + 1];
|
(*value_.map_)[keey] = (*this)[i + 1];
|
||||||
}
|
}
|
||||||
// erase the last one ("leftover")
|
// erase the last one ("leftover")
|
||||||
CZString keyLast(oldSize - 1);
|
CZString keyLast(oldSize - 1);
|
||||||
@@ -1103,16 +1206,16 @@ Value Value::get(const CppTL::ConstString& key,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool Value::isMember(char const* key, char const* end) const
|
bool Value::isMember(char const* key, char const* cend) const
|
||||||
{
|
{
|
||||||
Value const* value = find(key, end);
|
Value const* value = find(key, cend);
|
||||||
return NULL != value;
|
return NULL != value;
|
||||||
}
|
}
|
||||||
bool Value::isMember(char const* key) const
|
bool Value::isMember(char const* key) const
|
||||||
{
|
{
|
||||||
return isMember(key, key + strlen(key));
|
return isMember(key, key + strlen(key));
|
||||||
}
|
}
|
||||||
bool Value::isMember(std::string const& key) const
|
bool Value::isMember(JSONCPP_STRING const& key) const
|
||||||
{
|
{
|
||||||
return isMember(key.data(), key.data() + key.length());
|
return isMember(key.data(), key.data() + key.length());
|
||||||
}
|
}
|
||||||
@@ -1134,7 +1237,7 @@ Value::Members Value::getMemberNames() const {
|
|||||||
ObjectValues::const_iterator it = value_.map_->begin();
|
ObjectValues::const_iterator it = value_.map_->begin();
|
||||||
ObjectValues::const_iterator itEnd = value_.map_->end();
|
ObjectValues::const_iterator itEnd = value_.map_->end();
|
||||||
for (; it != itEnd; ++it) {
|
for (; it != itEnd; ++it) {
|
||||||
members.push_back(std::string((*it).first.data(),
|
members.push_back(JSONCPP_STRING((*it).first.data(),
|
||||||
(*it).first.length()));
|
(*it).first.length()));
|
||||||
}
|
}
|
||||||
return members;
|
return members;
|
||||||
@@ -1177,7 +1280,11 @@ bool Value::isBool() const { return type_ == booleanValue; }
|
|||||||
bool Value::isInt() const {
|
bool Value::isInt() const {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case intValue:
|
case intValue:
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
return value_.int_ >= minInt && value_.int_ <= maxInt;
|
return value_.int_ >= minInt && value_.int_ <= maxInt;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
case uintValue:
|
case uintValue:
|
||||||
return value_.uint_ <= UInt(maxInt);
|
return value_.uint_ <= UInt(maxInt);
|
||||||
case realValue:
|
case realValue:
|
||||||
@@ -1192,9 +1299,17 @@ bool Value::isInt() const {
|
|||||||
bool Value::isUInt() const {
|
bool Value::isUInt() const {
|
||||||
switch (type_) {
|
switch (type_) {
|
||||||
case intValue:
|
case intValue:
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
|
return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
|
||||||
|
#else
|
||||||
|
return value_.int_ >= 0;
|
||||||
|
#endif
|
||||||
case uintValue:
|
case uintValue:
|
||||||
|
#if defined(JSON_HAS_INT64)
|
||||||
return value_.uint_ <= maxUInt;
|
return value_.uint_ <= maxUInt;
|
||||||
|
#else
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
case realValue:
|
case realValue:
|
||||||
return value_.real_ >= 0 && value_.real_ <= maxUInt &&
|
return value_.real_ >= 0 && value_.real_ <= maxUInt &&
|
||||||
IsIntegral(value_.real_);
|
IsIntegral(value_.real_);
|
||||||
@@ -1245,16 +1360,28 @@ bool Value::isUInt64() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isIntegral() const {
|
bool Value::isIntegral() const {
|
||||||
|
switch (type_) {
|
||||||
|
case intValue:
|
||||||
|
case uintValue:
|
||||||
|
return true;
|
||||||
|
case realValue:
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
return isInt64() || isUInt64();
|
// 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
|
||||||
|
// require the value to be strictly less than the limit.
|
||||||
|
return value_.real_ >= double(minInt64) && value_.real_ < maxUInt64AsDouble && IsIntegral(value_.real_);
|
||||||
#else
|
#else
|
||||||
return isInt() || isUInt();
|
return value_.real_ >= minInt && value_.real_ <= maxUInt && IsIntegral(value_.real_);
|
||||||
#endif
|
#endif // JSON_HAS_INT64
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
|
bool Value::isDouble() const { return type_ == intValue || type_ == uintValue || type_ == realValue; }
|
||||||
|
|
||||||
bool Value::isNumeric() const { return isIntegral() || isDouble(); }
|
bool Value::isNumeric() const { return isDouble(); }
|
||||||
|
|
||||||
bool Value::isString() const { return type_ == stringValue; }
|
bool Value::isString() const { return type_ == stringValue; }
|
||||||
|
|
||||||
@@ -1276,7 +1403,7 @@ void Value::setComment(const char* comment, CommentPlacement placement) {
|
|||||||
setComment(comment, strlen(comment), placement);
|
setComment(comment, strlen(comment), placement);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::setComment(const std::string& comment, CommentPlacement placement) {
|
void Value::setComment(const JSONCPP_STRING& comment, CommentPlacement placement) {
|
||||||
setComment(comment.c_str(), comment.length(), placement);
|
setComment(comment.c_str(), comment.length(), placement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1284,21 +1411,21 @@ bool Value::hasComment(CommentPlacement placement) const {
|
|||||||
return comments_ != 0 && comments_[placement].comment_ != 0;
|
return comments_ != 0 && comments_[placement].comment_ != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Value::getComment(CommentPlacement placement) const {
|
JSONCPP_STRING Value::getComment(CommentPlacement placement) const {
|
||||||
if (hasComment(placement))
|
if (hasComment(placement))
|
||||||
return comments_[placement].comment_;
|
return comments_[placement].comment_;
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Value::setOffsetStart(size_t start) { start_ = start; }
|
void Value::setOffsetStart(ptrdiff_t start) { start_ = start; }
|
||||||
|
|
||||||
void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
|
void Value::setOffsetLimit(ptrdiff_t limit) { limit_ = limit; }
|
||||||
|
|
||||||
size_t Value::getOffsetStart() const { return start_; }
|
ptrdiff_t Value::getOffsetStart() const { return start_; }
|
||||||
|
|
||||||
size_t Value::getOffsetLimit() const { return limit_; }
|
ptrdiff_t Value::getOffsetLimit() const { return limit_; }
|
||||||
|
|
||||||
std::string Value::toStyledString() const {
|
JSONCPP_STRING Value::toStyledString() const {
|
||||||
StyledWriter writer;
|
StyledWriter writer;
|
||||||
return writer.write(*this);
|
return writer.write(*this);
|
||||||
}
|
}
|
||||||
@@ -1366,19 +1493,20 @@ PathArgument::PathArgument(ArrayIndex index)
|
|||||||
PathArgument::PathArgument(const char* key)
|
PathArgument::PathArgument(const char* key)
|
||||||
: key_(key), index_(), kind_(kindKey) {}
|
: key_(key), index_(), kind_(kindKey) {}
|
||||||
|
|
||||||
PathArgument::PathArgument(const std::string& key)
|
PathArgument::PathArgument(const JSONCPP_STRING& key)
|
||||||
: key_(key.c_str()), index_(), kind_(kindKey) {}
|
: key_(key.c_str()), index_(), kind_(kindKey) {}
|
||||||
|
|
||||||
// class Path
|
// class Path
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
Path::Path(const std::string& path,
|
Path::Path(const JSONCPP_STRING& path,
|
||||||
const PathArgument& a1,
|
const PathArgument& a1,
|
||||||
const PathArgument& a2,
|
const PathArgument& a2,
|
||||||
const PathArgument& a3,
|
const PathArgument& a3,
|
||||||
const PathArgument& a4,
|
const PathArgument& a4,
|
||||||
const PathArgument& a5) {
|
const PathArgument& a5) {
|
||||||
InArgs in;
|
InArgs in;
|
||||||
|
in.reserve(5);
|
||||||
in.push_back(&a1);
|
in.push_back(&a1);
|
||||||
in.push_back(&a2);
|
in.push_back(&a2);
|
||||||
in.push_back(&a3);
|
in.push_back(&a3);
|
||||||
@@ -1387,7 +1515,7 @@ Path::Path(const std::string& path,
|
|||||||
makePath(path, in);
|
makePath(path, in);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Path::makePath(const std::string& path, const InArgs& in) {
|
void Path::makePath(const JSONCPP_STRING& path, const InArgs& in) {
|
||||||
const char* current = path.c_str();
|
const char* current = path.c_str();
|
||||||
const char* end = current + path.length();
|
const char* end = current + path.length();
|
||||||
InArgs::const_iterator itInArg = in.begin();
|
InArgs::const_iterator itInArg = in.begin();
|
||||||
@@ -1402,23 +1530,23 @@ void Path::makePath(const std::string& path, const InArgs& in) {
|
|||||||
index = index * 10 + ArrayIndex(*current - '0');
|
index = index * 10 + ArrayIndex(*current - '0');
|
||||||
args_.push_back(index);
|
args_.push_back(index);
|
||||||
}
|
}
|
||||||
if (current == end || *current++ != ']')
|
if (current == end || *++current != ']')
|
||||||
invalidPath(path, int(current - path.c_str()));
|
invalidPath(path, int(current - path.c_str()));
|
||||||
} else if (*current == '%') {
|
} else if (*current == '%') {
|
||||||
addPathInArg(path, in, itInArg, PathArgument::kindKey);
|
addPathInArg(path, in, itInArg, PathArgument::kindKey);
|
||||||
++current;
|
++current;
|
||||||
} else if (*current == '.') {
|
} else if (*current == '.' || *current == ']') {
|
||||||
++current;
|
++current;
|
||||||
} else {
|
} else {
|
||||||
const char* beginName = current;
|
const char* beginName = current;
|
||||||
while (current != end && !strchr("[.", *current))
|
while (current != end && !strchr("[.", *current))
|
||||||
++current;
|
++current;
|
||||||
args_.push_back(std::string(beginName, current));
|
args_.push_back(JSONCPP_STRING(beginName, current));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Path::addPathInArg(const std::string& /*path*/,
|
void Path::addPathInArg(const JSONCPP_STRING& /*path*/,
|
||||||
const InArgs& in,
|
const InArgs& in,
|
||||||
InArgs::const_iterator& itInArg,
|
InArgs::const_iterator& itInArg,
|
||||||
PathArgument::Kind kind) {
|
PathArgument::Kind kind) {
|
||||||
@@ -1427,11 +1555,11 @@ void Path::addPathInArg(const std::string& /*path*/,
|
|||||||
} else if ((*itInArg)->kind_ != kind) {
|
} else if ((*itInArg)->kind_ != kind) {
|
||||||
// Error: bad argument type
|
// Error: bad argument type
|
||||||
} else {
|
} else {
|
||||||
args_.push_back(**itInArg);
|
args_.push_back(**itInArg++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
|
void Path::invalidPath(const JSONCPP_STRING& /*path*/, int /*location*/) {
|
||||||
// Error: invalid path.
|
// Error: invalid path.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1442,16 +1570,19 @@ const Value& Path::resolve(const Value& root) const {
|
|||||||
if (arg.kind_ == PathArgument::kindIndex) {
|
if (arg.kind_ == PathArgument::kindIndex) {
|
||||||
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
if (!node->isArray() || !node->isValidIndex(arg.index_)) {
|
||||||
// Error: unable to resolve path (array value expected at position...
|
// Error: unable to resolve path (array value expected at position...
|
||||||
|
return Value::null;
|
||||||
}
|
}
|
||||||
node = &((*node)[arg.index_]);
|
node = &((*node)[arg.index_]);
|
||||||
} else if (arg.kind_ == PathArgument::kindKey) {
|
} else if (arg.kind_ == PathArgument::kindKey) {
|
||||||
if (!node->isObject()) {
|
if (!node->isObject()) {
|
||||||
// Error: unable to resolve path (object value expected at position...)
|
// Error: unable to resolve path (object value expected at position...)
|
||||||
|
return Value::null;
|
||||||
}
|
}
|
||||||
node = &((*node)[arg.key_]);
|
node = &((*node)[arg.key_]);
|
||||||
if (node == &Value::nullRef) {
|
if (node == &Value::nullSingleton()) {
|
||||||
// Error: unable to resolve path (object has no member named '' at
|
// Error: unable to resolve path (object has no member named '' at
|
||||||
// position...)
|
// position...)
|
||||||
|
return Value::null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1470,7 +1601,7 @@ Value Path::resolve(const Value& root, const Value& defaultValue) const {
|
|||||||
if (!node->isObject())
|
if (!node->isObject())
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
node = &((*node)[arg.key_]);
|
node = &((*node)[arg.key_]);
|
||||||
if (node == &Value::nullRef)
|
if (node == &Value::nullSingleton())
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -92,19 +92,27 @@ UInt ValueIteratorBase::index() const {
|
|||||||
return Value::UInt(-1);
|
return Value::UInt(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONCPP_STRING ValueIteratorBase::name() const {
|
||||||
|
char const* keey;
|
||||||
|
char const* end;
|
||||||
|
keey = memberName(&end);
|
||||||
|
if (!keey) return JSONCPP_STRING();
|
||||||
|
return JSONCPP_STRING(keey, end);
|
||||||
|
}
|
||||||
|
|
||||||
char const* ValueIteratorBase::memberName() const {
|
char const* ValueIteratorBase::memberName() const {
|
||||||
const char* name = (*current_).first.data();
|
const char* cname = (*current_).first.data();
|
||||||
return name ? name : "";
|
return cname ? cname : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
char const* ValueIteratorBase::memberName(char const** end) const {
|
char const* ValueIteratorBase::memberName(char const** end) const {
|
||||||
const char* name = (*current_).first.data();
|
const char* cname = (*current_).first.data();
|
||||||
if (!name) {
|
if (!cname) {
|
||||||
*end = NULL;
|
*end = NULL;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
*end = name + (*current_).first.length();
|
*end = cname + (*current_).first.length();
|
||||||
return name;
|
return cname;
|
||||||
}
|
}
|
||||||
|
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
@@ -121,6 +129,9 @@ ValueConstIterator::ValueConstIterator(
|
|||||||
const Value::ObjectValues::iterator& current)
|
const Value::ObjectValues::iterator& current)
|
||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
|
ValueConstIterator::ValueConstIterator(ValueIterator const& other)
|
||||||
|
: ValueIteratorBase(other) {}
|
||||||
|
|
||||||
ValueConstIterator& ValueConstIterator::
|
ValueConstIterator& ValueConstIterator::
|
||||||
operator=(const ValueIteratorBase& other) {
|
operator=(const ValueIteratorBase& other) {
|
||||||
copy(other);
|
copy(other);
|
||||||
@@ -141,7 +152,9 @@ ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
|
|||||||
: ValueIteratorBase(current) {}
|
: ValueIteratorBase(current) {}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
ValueIterator::ValueIterator(const ValueConstIterator& other)
|
||||||
: ValueIteratorBase(other) {}
|
: ValueIteratorBase(other) {
|
||||||
|
throwRuntimeError("ConstIterator to Iterator should never be allowed.");
|
||||||
|
}
|
||||||
|
|
||||||
ValueIterator::ValueIterator(const ValueIterator& other)
|
ValueIterator::ValueIterator(const ValueIterator& other)
|
||||||
: ValueIteratorBase(other) {}
|
: ValueIteratorBase(other) {}
|
||||||
|
@@ -12,13 +12,57 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <stdexcept>
|
#include <cassert>
|
||||||
#include <assert.h>
|
#include <cstring>
|
||||||
#include <math.h>
|
#include <cstdio>
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if defined(_MSC_VER) && _MSC_VER < 1500 // VC++ 8.0 and below
|
#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
|
||||||
|
#include <float.h>
|
||||||
|
#define isfinite _finite
|
||||||
|
#elif defined(__sun) && defined(__SVR4) //Solaris
|
||||||
|
#if !defined(isfinite)
|
||||||
|
#include <ieeefp.h>
|
||||||
|
#define isfinite finite
|
||||||
|
#endif
|
||||||
|
#elif defined(_AIX)
|
||||||
|
#if !defined(isfinite)
|
||||||
|
#include <math.h>
|
||||||
|
#define isfinite finite
|
||||||
|
#endif
|
||||||
|
#elif defined(__hpux)
|
||||||
|
#if !defined(isfinite)
|
||||||
|
#if defined(__ia64) && !defined(finite)
|
||||||
|
#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
|
||||||
|
_Isfinitef(x) : _IsFinite(x)))
|
||||||
|
#else
|
||||||
|
#include <math.h>
|
||||||
|
#define isfinite finite
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <cmath>
|
||||||
|
#if !(defined(__QNXNTO__)) // QNX already defines isfinite
|
||||||
|
#define isfinite std::isfinite
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
|
||||||
|
#define snprintf sprintf_s
|
||||||
|
#elif _MSC_VER >= 1900 // VC++ 14.0 and above
|
||||||
|
#define snprintf std::snprintf
|
||||||
|
#else
|
||||||
|
#define snprintf _snprintf
|
||||||
|
#endif
|
||||||
|
#elif defined(__ANDROID__) || defined(__QNXNTO__)
|
||||||
|
#define snprintf snprintf
|
||||||
|
#elif __cplusplus >= 201103L
|
||||||
|
#if !defined(__MINGW32__) && !defined(__CYGWIN__)
|
||||||
|
#define snprintf std::snprintf
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__BORLANDC__)
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
#define isfinite _finite
|
#define isfinite _finite
|
||||||
#define snprintf _snprintf
|
#define snprintf _snprintf
|
||||||
@@ -29,14 +73,9 @@
|
|||||||
#pragma warning(disable : 4996)
|
#pragma warning(disable : 4996)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(__sun) && defined(__SVR4) //Solaris
|
|
||||||
#include <ieeefp.h>
|
|
||||||
#define isfinite finite
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace Json {
|
namespace Json {
|
||||||
|
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
|
||||||
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
|
typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
|
||||||
#else
|
#else
|
||||||
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
|
typedef std::auto_ptr<StreamWriter> StreamWriterPtr;
|
||||||
@@ -60,20 +99,23 @@ static bool containsControlCharacter0(const char* str, unsigned len) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string valueToString(LargestInt value) {
|
JSONCPP_STRING valueToString(LargestInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
char* current = buffer + sizeof(buffer);
|
char* current = buffer + sizeof(buffer);
|
||||||
bool isNegative = value < 0;
|
if (value == Value::minLargestInt) {
|
||||||
if (isNegative)
|
uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
|
||||||
value = -value;
|
|
||||||
uintToString(LargestUInt(value), current);
|
|
||||||
if (isNegative)
|
|
||||||
*--current = '-';
|
*--current = '-';
|
||||||
|
} else if (value < 0) {
|
||||||
|
uintToString(LargestUInt(-value), current);
|
||||||
|
*--current = '-';
|
||||||
|
} else {
|
||||||
|
uintToString(LargestUInt(value), current);
|
||||||
|
}
|
||||||
assert(current >= buffer);
|
assert(current >= buffer);
|
||||||
return current;
|
return current;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string valueToString(LargestUInt value) {
|
JSONCPP_STRING valueToString(LargestUInt value) {
|
||||||
UIntToStringBuffer buffer;
|
UIntToStringBuffer buffer;
|
||||||
char* current = buffer + sizeof(buffer);
|
char* current = buffer + sizeof(buffer);
|
||||||
uintToString(value, current);
|
uintToString(value, current);
|
||||||
@@ -83,68 +125,70 @@ std::string valueToString(LargestUInt value) {
|
|||||||
|
|
||||||
#if defined(JSON_HAS_INT64)
|
#if defined(JSON_HAS_INT64)
|
||||||
|
|
||||||
std::string valueToString(Int value) {
|
JSONCPP_STRING valueToString(Int value) {
|
||||||
return valueToString(LargestInt(value));
|
return valueToString(LargestInt(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string valueToString(UInt value) {
|
JSONCPP_STRING valueToString(UInt value) {
|
||||||
return valueToString(LargestUInt(value));
|
return valueToString(LargestUInt(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // # if defined(JSON_HAS_INT64)
|
#endif // # if defined(JSON_HAS_INT64)
|
||||||
|
|
||||||
std::string valueToString(double value) {
|
namespace {
|
||||||
|
JSONCPP_STRING valueToString(double value, bool useSpecialFloats, unsigned int precision) {
|
||||||
// Allocate a buffer that is more than large enough to store the 16 digits of
|
// Allocate a buffer that is more than large enough to store the 16 digits of
|
||||||
// precision requested below.
|
// precision requested below.
|
||||||
char buffer[32];
|
char buffer[36];
|
||||||
int len = -1;
|
int len = -1;
|
||||||
|
|
||||||
// Print into the buffer. We need not request the alternative representation
|
char formatString[15];
|
||||||
// that always has a decimal point because JSON doesn't distingish the
|
snprintf(formatString, sizeof(formatString), "%%.%dg", precision);
|
||||||
// concepts of reals and integers.
|
|
||||||
#if defined(_MSC_VER) && defined(__STDC_SECURE_LIB__) // Use secure version with
|
// Print into the buffer. We need not request the alternative representation
|
||||||
// visual studio 2005 to
|
// that always has a decimal point because JSON doesn't distingish the
|
||||||
// avoid warning.
|
// concepts of reals and integers.
|
||||||
#if defined(WINCE)
|
|
||||||
len = _snprintf(buffer, sizeof(buffer), "%.17g", value);
|
|
||||||
#else
|
|
||||||
len = sprintf_s(buffer, sizeof(buffer), "%.17g", value);
|
|
||||||
#endif
|
|
||||||
#else
|
|
||||||
if (isfinite(value)) {
|
if (isfinite(value)) {
|
||||||
len = snprintf(buffer, sizeof(buffer), "%.17g", value);
|
len = snprintf(buffer, sizeof(buffer), formatString, value);
|
||||||
|
fixNumericLocale(buffer, buffer + len);
|
||||||
|
|
||||||
|
// try to ensure we preserve the fact that this was given to us as a double on input
|
||||||
|
if (!strstr(buffer, ".") && !strstr(buffer, "e")) {
|
||||||
|
strcat(buffer, ".0");
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// IEEE standard states that NaN values will not compare to themselves
|
// IEEE standard states that NaN values will not compare to themselves
|
||||||
if (value != value) {
|
if (value != value) {
|
||||||
len = snprintf(buffer, sizeof(buffer), "null");
|
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
|
||||||
} else if (value < 0) {
|
} else if (value < 0) {
|
||||||
len = snprintf(buffer, sizeof(buffer), "-1e+9999");
|
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
|
||||||
} else {
|
} else {
|
||||||
len = snprintf(buffer, sizeof(buffer), "1e+9999");
|
len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
|
||||||
}
|
}
|
||||||
// For those, we do not need to call fixNumLoc, but it is fast.
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
assert(len >= 0);
|
assert(len >= 0);
|
||||||
fixNumericLocale(buffer, buffer + len);
|
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::string valueToString(bool value) { return value ? "true" : "false"; }
|
JSONCPP_STRING valueToString(double value) { return valueToString(value, false, 17); }
|
||||||
|
|
||||||
std::string valueToQuotedString(const char* value) {
|
JSONCPP_STRING valueToString(bool value) { return value ? "true" : "false"; }
|
||||||
|
|
||||||
|
JSONCPP_STRING valueToQuotedString(const char* value) {
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
return "";
|
return "";
|
||||||
// Not sure how to handle unicode...
|
// Not sure how to handle unicode...
|
||||||
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
|
if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
|
||||||
!containsControlCharacter(value))
|
!containsControlCharacter(value))
|
||||||
return std::string("\"") + value + "\"";
|
return JSONCPP_STRING("\"") + value + "\"";
|
||||||
// We have to walk value and escape any special characters.
|
// We have to walk value and escape any special characters.
|
||||||
// Appending to std::string is not efficient, but this should be rare.
|
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
|
||||||
// (Note: forward slashes are *not* rare, but I am not escaping them.)
|
// (Note: forward slashes are *not* rare, but I am not escaping them.)
|
||||||
std::string::size_type maxsize =
|
JSONCPP_STRING::size_type maxsize =
|
||||||
strlen(value) * 2 + 3; // allescaped+quotes+NULL
|
strlen(value) * 2 + 3; // allescaped+quotes+NULL
|
||||||
std::string result;
|
JSONCPP_STRING result;
|
||||||
result.reserve(maxsize); // to avoid lots of mallocs
|
result.reserve(maxsize); // to avoid lots of mallocs
|
||||||
result += "\"";
|
result += "\"";
|
||||||
for (const char* c = value; *c != 0; ++c) {
|
for (const char* c = value; *c != 0; ++c) {
|
||||||
@@ -180,7 +224,7 @@ std::string valueToQuotedString(const char* value) {
|
|||||||
// sequence from occurring.
|
// sequence from occurring.
|
||||||
default:
|
default:
|
||||||
if (isControlCharacter(*c)) {
|
if (isControlCharacter(*c)) {
|
||||||
std::ostringstream oss;
|
JSONCPP_OSTRINGSTREAM oss;
|
||||||
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
|
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
|
||||||
<< std::setw(4) << static_cast<int>(*c);
|
<< std::setw(4) << static_cast<int>(*c);
|
||||||
result += oss.str();
|
result += oss.str();
|
||||||
@@ -209,19 +253,19 @@ static char const* strnpbrk(char const* s, char const* accept, size_t n) {
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
static std::string valueToQuotedStringN(const char* value, unsigned length) {
|
static JSONCPP_STRING valueToQuotedStringN(const char* value, unsigned length) {
|
||||||
if (value == NULL)
|
if (value == NULL)
|
||||||
return "";
|
return "";
|
||||||
// Not sure how to handle unicode...
|
// Not sure how to handle unicode...
|
||||||
if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
|
if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
|
||||||
!containsControlCharacter0(value, length))
|
!containsControlCharacter0(value, length))
|
||||||
return std::string("\"") + value + "\"";
|
return JSONCPP_STRING("\"") + value + "\"";
|
||||||
// We have to walk value and escape any special characters.
|
// We have to walk value and escape any special characters.
|
||||||
// Appending to std::string is not efficient, but this should be rare.
|
// Appending to JSONCPP_STRING is not efficient, but this should be rare.
|
||||||
// (Note: forward slashes are *not* rare, but I am not escaping them.)
|
// (Note: forward slashes are *not* rare, but I am not escaping them.)
|
||||||
std::string::size_type maxsize =
|
JSONCPP_STRING::size_type maxsize =
|
||||||
length * 2 + 3; // allescaped+quotes+NULL
|
length * 2 + 3; // allescaped+quotes+NULL
|
||||||
std::string result;
|
JSONCPP_STRING result;
|
||||||
result.reserve(maxsize); // to avoid lots of mallocs
|
result.reserve(maxsize); // to avoid lots of mallocs
|
||||||
result += "\"";
|
result += "\"";
|
||||||
char const* end = value + length;
|
char const* end = value + length;
|
||||||
@@ -258,7 +302,7 @@ static std::string valueToQuotedStringN(const char* value, unsigned length) {
|
|||||||
// sequence from occurring.
|
// sequence from occurring.
|
||||||
default:
|
default:
|
||||||
if ((isControlCharacter(*c)) || (*c == 0)) {
|
if ((isControlCharacter(*c)) || (*c == 0)) {
|
||||||
std::ostringstream oss;
|
JSONCPP_OSTRINGSTREAM oss;
|
||||||
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
|
oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
|
||||||
<< std::setw(4) << static_cast<int>(*c);
|
<< std::setw(4) << static_cast<int>(*c);
|
||||||
result += oss.str();
|
result += oss.str();
|
||||||
@@ -289,8 +333,8 @@ void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
|
|||||||
|
|
||||||
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
|
void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
|
||||||
|
|
||||||
std::string FastWriter::write(const Value& root) {
|
JSONCPP_STRING FastWriter::write(const Value& root) {
|
||||||
document_ = "";
|
document_.clear();
|
||||||
writeValue(root);
|
writeValue(root);
|
||||||
if (!omitEndingLineFeed_)
|
if (!omitEndingLineFeed_)
|
||||||
document_ += "\n";
|
document_ += "\n";
|
||||||
@@ -313,15 +357,21 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
document_ += valueToString(value.asDouble());
|
document_ += valueToString(value.asDouble());
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
document_ += valueToQuotedString(value.asCString());
|
{
|
||||||
|
// Is NULL possible for value.string_? No.
|
||||||
|
char const* str;
|
||||||
|
char const* end;
|
||||||
|
bool ok = value.getString(&str, &end);
|
||||||
|
if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
document_ += valueToString(value.asBool());
|
document_ += valueToString(value.asBool());
|
||||||
break;
|
break;
|
||||||
case arrayValue: {
|
case arrayValue: {
|
||||||
document_ += '[';
|
document_ += '[';
|
||||||
int size = value.size();
|
ArrayIndex size = value.size();
|
||||||
for (int index = 0; index < size; ++index) {
|
for (ArrayIndex index = 0; index < size; ++index) {
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
document_ += ',';
|
document_ += ',';
|
||||||
writeValue(value[index]);
|
writeValue(value[index]);
|
||||||
@@ -333,10 +383,10 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
document_ += '{';
|
document_ += '{';
|
||||||
for (Value::Members::iterator it = members.begin(); it != members.end();
|
for (Value::Members::iterator it = members.begin(); it != members.end();
|
||||||
++it) {
|
++it) {
|
||||||
const std::string& name = *it;
|
const JSONCPP_STRING& name = *it;
|
||||||
if (it != members.begin())
|
if (it != members.begin())
|
||||||
document_ += ',';
|
document_ += ',';
|
||||||
document_ += valueToQuotedStringN(name.data(), name.length());
|
document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
|
||||||
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
|
document_ += yamlCompatiblityEnabled_ ? ": " : ":";
|
||||||
writeValue(value[name]);
|
writeValue(value[name]);
|
||||||
}
|
}
|
||||||
@@ -351,10 +401,10 @@ void FastWriter::writeValue(const Value& value) {
|
|||||||
StyledWriter::StyledWriter()
|
StyledWriter::StyledWriter()
|
||||||
: rightMargin_(74), indentSize_(3), addChildValues_() {}
|
: rightMargin_(74), indentSize_(3), addChildValues_() {}
|
||||||
|
|
||||||
std::string StyledWriter::write(const Value& root) {
|
JSONCPP_STRING StyledWriter::write(const Value& root) {
|
||||||
document_ = "";
|
document_.clear();
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
indentString_ = "";
|
indentString_.clear();
|
||||||
writeCommentBeforeValue(root);
|
writeCommentBeforeValue(root);
|
||||||
writeValue(root);
|
writeValue(root);
|
||||||
writeCommentAfterValueOnSameLine(root);
|
writeCommentAfterValueOnSameLine(root);
|
||||||
@@ -378,7 +428,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
{
|
{
|
||||||
// Is NULL is possible for value.string_?
|
// Is NULL possible for value.string_? No.
|
||||||
char const* str;
|
char const* str;
|
||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
@@ -401,7 +451,7 @@ void StyledWriter::writeValue(const Value& value) {
|
|||||||
indent();
|
indent();
|
||||||
Value::Members::iterator it = members.begin();
|
Value::Members::iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const std::string& name = *it;
|
const JSONCPP_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()));
|
||||||
@@ -465,26 +515,25 @@ void StyledWriter::writeArrayValue(const Value& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StyledWriter::isMultineArray(const Value& value) {
|
bool StyledWriter::isMultineArray(const Value& value) {
|
||||||
int size = value.size();
|
ArrayIndex const size = value.size();
|
||||||
bool isMultiLine = size * 3 >= rightMargin_;
|
bool isMultiLine = size * 3 >= rightMargin_;
|
||||||
childValues_.clear();
|
childValues_.clear();
|
||||||
for (int index = 0; index < size && !isMultiLine; ++index) {
|
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
|
||||||
const Value& childValue = value[index];
|
const Value& childValue = value[index];
|
||||||
isMultiLine =
|
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
|
||||||
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
|
|
||||||
childValue.size() > 0);
|
childValue.size() > 0);
|
||||||
}
|
}
|
||||||
if (!isMultiLine) // check if line length > max line length
|
if (!isMultiLine) // check if line length > max line length
|
||||||
{
|
{
|
||||||
childValues_.reserve(size);
|
childValues_.reserve(size);
|
||||||
addChildValues_ = true;
|
addChildValues_ = true;
|
||||||
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
||||||
for (int index = 0; index < size; ++index) {
|
for (ArrayIndex index = 0; index < size; ++index) {
|
||||||
if (hasCommentForValue(value[index])) {
|
if (hasCommentForValue(value[index])) {
|
||||||
isMultiLine = true;
|
isMultiLine = true;
|
||||||
}
|
}
|
||||||
writeValue(value[index]);
|
writeValue(value[index]);
|
||||||
lineLength += int(childValues_[index].length());
|
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
|
||||||
}
|
}
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
||||||
@@ -492,7 +541,7 @@ bool StyledWriter::isMultineArray(const Value& value) {
|
|||||||
return isMultiLine;
|
return isMultiLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledWriter::pushValue(const std::string& value) {
|
void StyledWriter::pushValue(const JSONCPP_STRING& value) {
|
||||||
if (addChildValues_)
|
if (addChildValues_)
|
||||||
childValues_.push_back(value);
|
childValues_.push_back(value);
|
||||||
else
|
else
|
||||||
@@ -510,15 +559,15 @@ void StyledWriter::writeIndent() {
|
|||||||
document_ += indentString_;
|
document_ += indentString_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledWriter::writeWithIndent(const std::string& value) {
|
void StyledWriter::writeWithIndent(const JSONCPP_STRING& value) {
|
||||||
writeIndent();
|
writeIndent();
|
||||||
document_ += value;
|
document_ += value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
|
void StyledWriter::indent() { indentString_ += JSONCPP_STRING(indentSize_, ' '); }
|
||||||
|
|
||||||
void StyledWriter::unindent() {
|
void StyledWriter::unindent() {
|
||||||
assert(int(indentString_.size()) >= indentSize_);
|
assert(indentString_.size() >= indentSize_);
|
||||||
indentString_.resize(indentString_.size() - indentSize_);
|
indentString_.resize(indentString_.size() - indentSize_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -528,8 +577,8 @@ void StyledWriter::writeCommentBeforeValue(const Value& root) {
|
|||||||
|
|
||||||
document_ += "\n";
|
document_ += "\n";
|
||||||
writeIndent();
|
writeIndent();
|
||||||
const std::string& comment = root.getComment(commentBefore);
|
const JSONCPP_STRING& comment = root.getComment(commentBefore);
|
||||||
std::string::const_iterator iter = comment.begin();
|
JSONCPP_STRING::const_iterator iter = comment.begin();
|
||||||
while (iter != comment.end()) {
|
while (iter != comment.end()) {
|
||||||
document_ += *iter;
|
document_ += *iter;
|
||||||
if (*iter == '\n' &&
|
if (*iter == '\n' &&
|
||||||
@@ -562,14 +611,14 @@ bool StyledWriter::hasCommentForValue(const Value& value) {
|
|||||||
// Class StyledStreamWriter
|
// Class StyledStreamWriter
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
StyledStreamWriter::StyledStreamWriter(std::string indentation)
|
StyledStreamWriter::StyledStreamWriter(JSONCPP_STRING indentation)
|
||||||
: document_(NULL), rightMargin_(74), indentation_(indentation),
|
: document_(NULL), rightMargin_(74), indentation_(indentation),
|
||||||
addChildValues_() {}
|
addChildValues_() {}
|
||||||
|
|
||||||
void StyledStreamWriter::write(std::ostream& out, const Value& root) {
|
void StyledStreamWriter::write(JSONCPP_OSTREAM& out, const Value& root) {
|
||||||
document_ = &out;
|
document_ = &out;
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
indentString_ = "";
|
indentString_.clear();
|
||||||
indented_ = true;
|
indented_ = true;
|
||||||
writeCommentBeforeValue(root);
|
writeCommentBeforeValue(root);
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
@@ -595,8 +644,15 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
pushValue(valueToString(value.asDouble()));
|
pushValue(valueToString(value.asDouble()));
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
pushValue(valueToQuotedString(value.asCString()));
|
{
|
||||||
|
// Is NULL possible for value.string_? No.
|
||||||
|
char const* str;
|
||||||
|
char const* end;
|
||||||
|
bool ok = value.getString(&str, &end);
|
||||||
|
if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
|
||||||
|
else pushValue("");
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case booleanValue:
|
case booleanValue:
|
||||||
pushValue(valueToString(value.asBool()));
|
pushValue(valueToString(value.asBool()));
|
||||||
break;
|
break;
|
||||||
@@ -612,7 +668,7 @@ void StyledStreamWriter::writeValue(const Value& value) {
|
|||||||
indent();
|
indent();
|
||||||
Value::Members::iterator it = members.begin();
|
Value::Members::iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
const std::string& name = *it;
|
const JSONCPP_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()));
|
||||||
@@ -678,26 +734,25 @@ void StyledStreamWriter::writeArrayValue(const Value& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool StyledStreamWriter::isMultineArray(const Value& value) {
|
bool StyledStreamWriter::isMultineArray(const Value& value) {
|
||||||
int size = value.size();
|
ArrayIndex const size = value.size();
|
||||||
bool isMultiLine = size * 3 >= rightMargin_;
|
bool isMultiLine = size * 3 >= rightMargin_;
|
||||||
childValues_.clear();
|
childValues_.clear();
|
||||||
for (int index = 0; index < size && !isMultiLine; ++index) {
|
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
|
||||||
const Value& childValue = value[index];
|
const Value& childValue = value[index];
|
||||||
isMultiLine =
|
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
|
||||||
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
|
|
||||||
childValue.size() > 0);
|
childValue.size() > 0);
|
||||||
}
|
}
|
||||||
if (!isMultiLine) // check if line length > max line length
|
if (!isMultiLine) // check if line length > max line length
|
||||||
{
|
{
|
||||||
childValues_.reserve(size);
|
childValues_.reserve(size);
|
||||||
addChildValues_ = true;
|
addChildValues_ = true;
|
||||||
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
||||||
for (int index = 0; index < size; ++index) {
|
for (ArrayIndex index = 0; index < size; ++index) {
|
||||||
if (hasCommentForValue(value[index])) {
|
if (hasCommentForValue(value[index])) {
|
||||||
isMultiLine = true;
|
isMultiLine = true;
|
||||||
}
|
}
|
||||||
writeValue(value[index]);
|
writeValue(value[index]);
|
||||||
lineLength += int(childValues_[index].length());
|
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
|
||||||
}
|
}
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
||||||
@@ -705,7 +760,7 @@ bool StyledStreamWriter::isMultineArray(const Value& value) {
|
|||||||
return isMultiLine;
|
return isMultiLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledStreamWriter::pushValue(const std::string& value) {
|
void StyledStreamWriter::pushValue(const JSONCPP_STRING& value) {
|
||||||
if (addChildValues_)
|
if (addChildValues_)
|
||||||
childValues_.push_back(value);
|
childValues_.push_back(value);
|
||||||
else
|
else
|
||||||
@@ -720,7 +775,7 @@ void StyledStreamWriter::writeIndent() {
|
|||||||
*document_ << '\n' << indentString_;
|
*document_ << '\n' << indentString_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StyledStreamWriter::writeWithIndent(const std::string& value) {
|
void StyledStreamWriter::writeWithIndent(const JSONCPP_STRING& value) {
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
*document_ << value;
|
*document_ << value;
|
||||||
indented_ = false;
|
indented_ = false;
|
||||||
@@ -738,8 +793,8 @@ void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
const std::string& comment = root.getComment(commentBefore);
|
const JSONCPP_STRING& comment = root.getComment(commentBefore);
|
||||||
std::string::const_iterator iter = comment.begin();
|
JSONCPP_STRING::const_iterator iter = comment.begin();
|
||||||
while (iter != comment.end()) {
|
while (iter != comment.end()) {
|
||||||
*document_ << *iter;
|
*document_ << *iter;
|
||||||
if (*iter == '\n' &&
|
if (*iter == '\n' &&
|
||||||
@@ -784,44 +839,50 @@ struct CommentStyle {
|
|||||||
struct BuiltStyledStreamWriter : public StreamWriter
|
struct BuiltStyledStreamWriter : public StreamWriter
|
||||||
{
|
{
|
||||||
BuiltStyledStreamWriter(
|
BuiltStyledStreamWriter(
|
||||||
std::string const& indentation,
|
JSONCPP_STRING const& indentation,
|
||||||
CommentStyle::Enum cs,
|
CommentStyle::Enum cs,
|
||||||
std::string const& colonSymbol,
|
JSONCPP_STRING const& colonSymbol,
|
||||||
std::string const& nullSymbol,
|
JSONCPP_STRING const& nullSymbol,
|
||||||
std::string const& endingLineFeedSymbol);
|
JSONCPP_STRING const& endingLineFeedSymbol,
|
||||||
virtual int write(Value const& root, std::ostream* sout);
|
bool useSpecialFloats,
|
||||||
|
unsigned int precision);
|
||||||
|
int write(Value const& root, JSONCPP_OSTREAM* sout) JSONCPP_OVERRIDE;
|
||||||
private:
|
private:
|
||||||
void writeValue(Value const& value);
|
void writeValue(Value const& value);
|
||||||
void writeArrayValue(Value const& value);
|
void writeArrayValue(Value const& value);
|
||||||
bool isMultineArray(Value const& value);
|
bool isMultineArray(Value const& value);
|
||||||
void pushValue(std::string const& value);
|
void pushValue(JSONCPP_STRING const& value);
|
||||||
void writeIndent();
|
void writeIndent();
|
||||||
void writeWithIndent(std::string const& value);
|
void writeWithIndent(JSONCPP_STRING const& value);
|
||||||
void indent();
|
void indent();
|
||||||
void unindent();
|
void unindent();
|
||||||
void writeCommentBeforeValue(Value const& root);
|
void writeCommentBeforeValue(Value const& root);
|
||||||
void writeCommentAfterValueOnSameLine(Value const& root);
|
void writeCommentAfterValueOnSameLine(Value const& root);
|
||||||
static bool hasCommentForValue(const Value& value);
|
static bool hasCommentForValue(const Value& value);
|
||||||
|
|
||||||
typedef std::vector<std::string> ChildValues;
|
typedef std::vector<JSONCPP_STRING> ChildValues;
|
||||||
|
|
||||||
ChildValues childValues_;
|
ChildValues childValues_;
|
||||||
std::string indentString_;
|
JSONCPP_STRING indentString_;
|
||||||
int rightMargin_;
|
unsigned int rightMargin_;
|
||||||
std::string indentation_;
|
JSONCPP_STRING indentation_;
|
||||||
CommentStyle::Enum cs_;
|
CommentStyle::Enum cs_;
|
||||||
std::string colonSymbol_;
|
JSONCPP_STRING colonSymbol_;
|
||||||
std::string nullSymbol_;
|
JSONCPP_STRING nullSymbol_;
|
||||||
std::string endingLineFeedSymbol_;
|
JSONCPP_STRING endingLineFeedSymbol_;
|
||||||
bool addChildValues_ : 1;
|
bool addChildValues_ : 1;
|
||||||
bool indented_ : 1;
|
bool indented_ : 1;
|
||||||
|
bool useSpecialFloats_ : 1;
|
||||||
|
unsigned int precision_;
|
||||||
};
|
};
|
||||||
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
||||||
std::string const& indentation,
|
JSONCPP_STRING const& indentation,
|
||||||
CommentStyle::Enum cs,
|
CommentStyle::Enum cs,
|
||||||
std::string const& colonSymbol,
|
JSONCPP_STRING const& colonSymbol,
|
||||||
std::string const& nullSymbol,
|
JSONCPP_STRING const& nullSymbol,
|
||||||
std::string const& endingLineFeedSymbol)
|
JSONCPP_STRING const& endingLineFeedSymbol,
|
||||||
|
bool useSpecialFloats,
|
||||||
|
unsigned int precision)
|
||||||
: rightMargin_(74)
|
: rightMargin_(74)
|
||||||
, indentation_(indentation)
|
, indentation_(indentation)
|
||||||
, cs_(cs)
|
, cs_(cs)
|
||||||
@@ -830,14 +891,16 @@ BuiltStyledStreamWriter::BuiltStyledStreamWriter(
|
|||||||
, endingLineFeedSymbol_(endingLineFeedSymbol)
|
, endingLineFeedSymbol_(endingLineFeedSymbol)
|
||||||
, addChildValues_(false)
|
, addChildValues_(false)
|
||||||
, indented_(false)
|
, indented_(false)
|
||||||
|
, useSpecialFloats_(useSpecialFloats)
|
||||||
|
, precision_(precision)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
|
int BuiltStyledStreamWriter::write(Value const& root, JSONCPP_OSTREAM* sout)
|
||||||
{
|
{
|
||||||
sout_ = sout;
|
sout_ = sout;
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
indented_ = true;
|
indented_ = true;
|
||||||
indentString_ = "";
|
indentString_.clear();
|
||||||
writeCommentBeforeValue(root);
|
writeCommentBeforeValue(root);
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
indented_ = true;
|
indented_ = true;
|
||||||
@@ -859,11 +922,11 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
pushValue(valueToString(value.asLargestUInt()));
|
pushValue(valueToString(value.asLargestUInt()));
|
||||||
break;
|
break;
|
||||||
case realValue:
|
case realValue:
|
||||||
pushValue(valueToString(value.asDouble()));
|
pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
|
||||||
break;
|
break;
|
||||||
case stringValue:
|
case stringValue:
|
||||||
{
|
{
|
||||||
// Is NULL is possible for value.string_?
|
// Is NULL is possible for value.string_? No.
|
||||||
char const* str;
|
char const* str;
|
||||||
char const* end;
|
char const* end;
|
||||||
bool ok = value.getString(&str, &end);
|
bool ok = value.getString(&str, &end);
|
||||||
@@ -886,10 +949,10 @@ void BuiltStyledStreamWriter::writeValue(Value const& value) {
|
|||||||
indent();
|
indent();
|
||||||
Value::Members::iterator it = members.begin();
|
Value::Members::iterator it = members.begin();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
std::string const& name = *it;
|
JSONCPP_STRING const& name = *it;
|
||||||
Value const& childValue = value[name];
|
Value const& childValue = value[name];
|
||||||
writeCommentBeforeValue(childValue);
|
writeCommentBeforeValue(childValue);
|
||||||
writeWithIndent(valueToQuotedStringN(name.data(), name.length()));
|
writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
|
||||||
*sout_ << colonSymbol_;
|
*sout_ << colonSymbol_;
|
||||||
writeValue(childValue);
|
writeValue(childValue);
|
||||||
if (++it == members.end()) {
|
if (++it == members.end()) {
|
||||||
@@ -944,7 +1007,7 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
|
|||||||
if (!indentation_.empty()) *sout_ << " ";
|
if (!indentation_.empty()) *sout_ << " ";
|
||||||
for (unsigned index = 0; index < size; ++index) {
|
for (unsigned index = 0; index < size; ++index) {
|
||||||
if (index > 0)
|
if (index > 0)
|
||||||
*sout_ << ", ";
|
*sout_ << ((!indentation_.empty()) ? ", " : ",");
|
||||||
*sout_ << childValues_[index];
|
*sout_ << childValues_[index];
|
||||||
}
|
}
|
||||||
if (!indentation_.empty()) *sout_ << " ";
|
if (!indentation_.empty()) *sout_ << " ";
|
||||||
@@ -954,26 +1017,25 @@ void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
|
bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
|
||||||
int size = value.size();
|
ArrayIndex const size = value.size();
|
||||||
bool isMultiLine = size * 3 >= rightMargin_;
|
bool isMultiLine = size * 3 >= rightMargin_;
|
||||||
childValues_.clear();
|
childValues_.clear();
|
||||||
for (int index = 0; index < size && !isMultiLine; ++index) {
|
for (ArrayIndex index = 0; index < size && !isMultiLine; ++index) {
|
||||||
Value const& childValue = value[index];
|
Value const& childValue = value[index];
|
||||||
isMultiLine =
|
isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
|
||||||
isMultiLine || ((childValue.isArray() || childValue.isObject()) &&
|
|
||||||
childValue.size() > 0);
|
childValue.size() > 0);
|
||||||
}
|
}
|
||||||
if (!isMultiLine) // check if line length > max line length
|
if (!isMultiLine) // check if line length > max line length
|
||||||
{
|
{
|
||||||
childValues_.reserve(size);
|
childValues_.reserve(size);
|
||||||
addChildValues_ = true;
|
addChildValues_ = true;
|
||||||
int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
ArrayIndex lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
|
||||||
for (int index = 0; index < size; ++index) {
|
for (ArrayIndex index = 0; index < size; ++index) {
|
||||||
if (hasCommentForValue(value[index])) {
|
if (hasCommentForValue(value[index])) {
|
||||||
isMultiLine = true;
|
isMultiLine = true;
|
||||||
}
|
}
|
||||||
writeValue(value[index]);
|
writeValue(value[index]);
|
||||||
lineLength += int(childValues_[index].length());
|
lineLength += static_cast<ArrayIndex>(childValues_[index].length());
|
||||||
}
|
}
|
||||||
addChildValues_ = false;
|
addChildValues_ = false;
|
||||||
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
isMultiLine = isMultiLine || lineLength >= rightMargin_;
|
||||||
@@ -981,7 +1043,7 @@ bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
|
|||||||
return isMultiLine;
|
return isMultiLine;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltStyledStreamWriter::pushValue(std::string const& value) {
|
void BuiltStyledStreamWriter::pushValue(JSONCPP_STRING const& value) {
|
||||||
if (addChildValues_)
|
if (addChildValues_)
|
||||||
childValues_.push_back(value);
|
childValues_.push_back(value);
|
||||||
else
|
else
|
||||||
@@ -1000,7 +1062,7 @@ void BuiltStyledStreamWriter::writeIndent() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
|
void BuiltStyledStreamWriter::writeWithIndent(JSONCPP_STRING const& value) {
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
*sout_ << value;
|
*sout_ << value;
|
||||||
indented_ = false;
|
indented_ = false;
|
||||||
@@ -1019,8 +1081,8 @@ void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!indented_) writeIndent();
|
if (!indented_) writeIndent();
|
||||||
const std::string& comment = root.getComment(commentBefore);
|
const JSONCPP_STRING& comment = root.getComment(commentBefore);
|
||||||
std::string::const_iterator iter = comment.begin();
|
JSONCPP_STRING::const_iterator iter = comment.begin();
|
||||||
while (iter != comment.end()) {
|
while (iter != comment.end()) {
|
||||||
*sout_ << *iter;
|
*sout_ << *iter;
|
||||||
if (*iter == '\n' &&
|
if (*iter == '\n' &&
|
||||||
@@ -1070,59 +1132,64 @@ StreamWriterBuilder::~StreamWriterBuilder()
|
|||||||
{}
|
{}
|
||||||
StreamWriter* StreamWriterBuilder::newStreamWriter() const
|
StreamWriter* StreamWriterBuilder::newStreamWriter() const
|
||||||
{
|
{
|
||||||
std::string indentation = settings_["indentation"].asString();
|
JSONCPP_STRING indentation = settings_["indentation"].asString();
|
||||||
std::string cs_str = settings_["commentStyle"].asString();
|
JSONCPP_STRING cs_str = settings_["commentStyle"].asString();
|
||||||
bool eyc = settings_["enableYAMLCompatibility"].asBool();
|
bool eyc = settings_["enableYAMLCompatibility"].asBool();
|
||||||
bool dnp = settings_["dropNullPlaceholders"].asBool();
|
bool dnp = settings_["dropNullPlaceholders"].asBool();
|
||||||
|
bool usf = settings_["useSpecialFloats"].asBool();
|
||||||
|
unsigned int pre = settings_["precision"].asUInt();
|
||||||
CommentStyle::Enum cs = CommentStyle::All;
|
CommentStyle::Enum cs = CommentStyle::All;
|
||||||
if (cs_str == "All") {
|
if (cs_str == "All") {
|
||||||
cs = CommentStyle::All;
|
cs = CommentStyle::All;
|
||||||
} else if (cs_str == "None") {
|
} else if (cs_str == "None") {
|
||||||
cs = CommentStyle::None;
|
cs = CommentStyle::None;
|
||||||
} else {
|
} else {
|
||||||
throw std::runtime_error("commentStyle must be 'All' or 'None'");
|
throwRuntimeError("commentStyle must be 'All' or 'None'");
|
||||||
}
|
}
|
||||||
std::string colonSymbol = " : ";
|
JSONCPP_STRING colonSymbol = " : ";
|
||||||
if (eyc) {
|
if (eyc) {
|
||||||
colonSymbol = ": ";
|
colonSymbol = ": ";
|
||||||
} else if (indentation.empty()) {
|
} else if (indentation.empty()) {
|
||||||
colonSymbol = ":";
|
colonSymbol = ":";
|
||||||
}
|
}
|
||||||
std::string nullSymbol = "null";
|
JSONCPP_STRING nullSymbol = "null";
|
||||||
if (dnp) {
|
if (dnp) {
|
||||||
nullSymbol = "";
|
nullSymbol.clear();
|
||||||
}
|
}
|
||||||
std::string endingLineFeedSymbol = "";
|
if (pre > 17) pre = 17;
|
||||||
|
JSONCPP_STRING endingLineFeedSymbol;
|
||||||
return new BuiltStyledStreamWriter(
|
return new BuiltStyledStreamWriter(
|
||||||
indentation, cs,
|
indentation, cs,
|
||||||
colonSymbol, nullSymbol, endingLineFeedSymbol);
|
colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
|
||||||
}
|
}
|
||||||
static void getValidWriterKeys(std::set<std::string>* valid_keys)
|
static void getValidWriterKeys(std::set<JSONCPP_STRING>* valid_keys)
|
||||||
{
|
{
|
||||||
valid_keys->clear();
|
valid_keys->clear();
|
||||||
valid_keys->insert("indentation");
|
valid_keys->insert("indentation");
|
||||||
valid_keys->insert("commentStyle");
|
valid_keys->insert("commentStyle");
|
||||||
valid_keys->insert("enableYAMLCompatibility");
|
valid_keys->insert("enableYAMLCompatibility");
|
||||||
valid_keys->insert("dropNullPlaceholders");
|
valid_keys->insert("dropNullPlaceholders");
|
||||||
|
valid_keys->insert("useSpecialFloats");
|
||||||
|
valid_keys->insert("precision");
|
||||||
}
|
}
|
||||||
bool StreamWriterBuilder::validate(Json::Value* invalid) const
|
bool StreamWriterBuilder::validate(Json::Value* invalid) const
|
||||||
{
|
{
|
||||||
Json::Value my_invalid;
|
Json::Value my_invalid;
|
||||||
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
if (!invalid) invalid = &my_invalid; // so we do not need to test for NULL
|
||||||
Json::Value& inv = *invalid;
|
Json::Value& inv = *invalid;
|
||||||
std::set<std::string> valid_keys;
|
std::set<JSONCPP_STRING> valid_keys;
|
||||||
getValidWriterKeys(&valid_keys);
|
getValidWriterKeys(&valid_keys);
|
||||||
Value::Members keys = settings_.getMemberNames();
|
Value::Members keys = settings_.getMemberNames();
|
||||||
size_t n = keys.size();
|
size_t n = keys.size();
|
||||||
for (size_t i = 0; i < n; ++i) {
|
for (size_t i = 0; i < n; ++i) {
|
||||||
std::string const& key = keys[i];
|
JSONCPP_STRING const& key = keys[i];
|
||||||
if (valid_keys.find(key) == valid_keys.end()) {
|
if (valid_keys.find(key) == valid_keys.end()) {
|
||||||
inv[key] = settings_[key];
|
inv[key] = settings_[key];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0u == inv.size();
|
return 0u == inv.size();
|
||||||
}
|
}
|
||||||
Value& StreamWriterBuilder::operator[](std::string key)
|
Value& StreamWriterBuilder::operator[](JSONCPP_STRING key)
|
||||||
{
|
{
|
||||||
return settings_[key];
|
return settings_[key];
|
||||||
}
|
}
|
||||||
@@ -1134,17 +1201,19 @@ void StreamWriterBuilder::setDefaults(Json::Value* settings)
|
|||||||
(*settings)["indentation"] = "\t";
|
(*settings)["indentation"] = "\t";
|
||||||
(*settings)["enableYAMLCompatibility"] = false;
|
(*settings)["enableYAMLCompatibility"] = false;
|
||||||
(*settings)["dropNullPlaceholders"] = false;
|
(*settings)["dropNullPlaceholders"] = false;
|
||||||
|
(*settings)["useSpecialFloats"] = false;
|
||||||
|
(*settings)["precision"] = 17;
|
||||||
//! [StreamWriterBuilderDefaults]
|
//! [StreamWriterBuilderDefaults]
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
|
JSONCPP_STRING writeString(StreamWriter::Factory const& builder, Value const& root) {
|
||||||
std::ostringstream sout;
|
JSONCPP_OSTRINGSTREAM sout;
|
||||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
return sout.str();
|
return sout.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& sout, Value const& root) {
|
JSONCPP_OSTREAM& operator<<(JSONCPP_OSTREAM& sout, Value const& root) {
|
||||||
StreamWriterBuilder builder;
|
StreamWriterBuilder builder;
|
||||||
StreamWriterPtr const writer(builder.newStreamWriter());
|
StreamWriterPtr const writer(builder.newStreamWriter());
|
||||||
writer->write(root, &sout);
|
writer->write(root, &sout);
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
// DO NOT EDIT. This file is generated by CMake from "version"
|
// DO NOT EDIT. This file (and "version") is generated by CMake.
|
||||||
// and "version.h.in" files.
|
|
||||||
// Run CMake configure step to update it.
|
// Run CMake configure step to update it.
|
||||||
#ifndef JSON_VERSION_H_INCLUDED
|
#ifndef JSON_VERSION_H_INCLUDED
|
||||||
# define JSON_VERSION_H_INCLUDED
|
# define JSON_VERSION_H_INCLUDED
|
||||||
@@ -11,4 +10,11 @@
|
|||||||
# define JSONCPP_VERSION_QUALIFIER
|
# define JSONCPP_VERSION_QUALIFIER
|
||||||
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
|
||||||
|
|
||||||
|
#ifdef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#undef JSONCPP_USING_SECURE_MEMORY
|
||||||
|
#endif
|
||||||
|
#define JSONCPP_USING_SECURE_MEMORY @JSONCPP_USE_SECURE_MEMORY@
|
||||||
|
// If non-zero, the library zeroes any memory that it has allocated before
|
||||||
|
// it frees its memory.
|
||||||
|
|
||||||
#endif // JSON_VERSION_H_INCLUDED
|
#endif // JSON_VERSION_H_INCLUDED
|
||||||
|
@@ -1,9 +1,5 @@
|
|||||||
# vim: et ts=4 sts=4 sw=4 tw=0
|
# vim: et ts=4 sts=4 sw=4 tw=0
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
|
||||||
ADD_DEFINITIONS( -DJSON_DLL )
|
|
||||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
|
||||||
|
|
||||||
ADD_EXECUTABLE( jsoncpp_test
|
ADD_EXECUTABLE( jsoncpp_test
|
||||||
jsontest.cpp
|
jsontest.cpp
|
||||||
jsontest.h
|
jsontest.h
|
||||||
@@ -11,11 +7,12 @@ ADD_EXECUTABLE( jsoncpp_test
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
IF(JSONCPP_LIB_BUILD_SHARED)
|
IF(BUILD_SHARED_LIBS)
|
||||||
|
ADD_DEFINITIONS( -DJSON_DLL )
|
||||||
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib)
|
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib)
|
||||||
ELSE(JSONCPP_LIB_BUILD_SHARED)
|
ELSE(BUILD_SHARED_LIBS)
|
||||||
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib_static)
|
TARGET_LINK_LIBRARIES(jsoncpp_test jsoncpp_lib_static)
|
||||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
ENDIF()
|
||||||
|
|
||||||
# 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)
|
||||||
@@ -23,19 +20,19 @@ ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
|||||||
# 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(JSONCPP_LIB_BUILD_SHARED)
|
IF(BUILD_SHARED_LIBS)
|
||||||
# First, copy the shared lib, for Microsoft.
|
# First, copy the shared lib, for Microsoft.
|
||||||
# Then, run the test executable.
|
# Then, run the test executable.
|
||||||
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
|
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:jsoncpp_lib> $<TARGET_FILE_DIR:jsoncpp_test>
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:jsoncpp_lib> $<TARGET_FILE_DIR:jsoncpp_test>
|
||||||
COMMAND $<TARGET_FILE:jsoncpp_test>)
|
COMMAND $<TARGET_FILE:jsoncpp_test>)
|
||||||
ELSE(JSONCPP_LIB_BUILD_SHARED)
|
ELSE(BUILD_SHARED_LIBS)
|
||||||
# Just run the test executable.
|
# Just run the test executable.
|
||||||
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
|
ADD_CUSTOM_COMMAND( TARGET jsoncpp_test
|
||||||
POST_BUILD
|
POST_BUILD
|
||||||
COMMAND $<TARGET_FILE:jsoncpp_test>)
|
COMMAND $<TARGET_FILE:jsoncpp_test>)
|
||||||
ENDIF(JSONCPP_LIB_BUILD_SHARED)
|
ENDIF()
|
||||||
ENDIF(JSONCPP_WITH_POST_BUILD_UNITTEST)
|
ENDIF()
|
||||||
|
|
||||||
SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
SET_TARGET_PROPERTIES(jsoncpp_test PROPERTIES OUTPUT_NAME jsoncpp_test)
|
||||||
|
@@ -81,7 +81,7 @@ TestResult::TestResult()
|
|||||||
predicateStackTail_ = &rootPredicateNode_;
|
predicateStackTail_ = &rootPredicateNode_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestResult::setTestName(const std::string& name) { name_ = name; }
|
void TestResult::setTestName(const JSONCPP_STRING& name) { name_ = name; }
|
||||||
|
|
||||||
TestResult&
|
TestResult&
|
||||||
TestResult::addFailure(const char* file, unsigned int line, const char* expr) {
|
TestResult::addFailure(const char* file, unsigned int line, const char* expr) {
|
||||||
@@ -163,7 +163,7 @@ void TestResult::printFailure(bool printTestName) const {
|
|||||||
Failures::const_iterator itEnd = failures_.end();
|
Failures::const_iterator itEnd = failures_.end();
|
||||||
for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) {
|
for (Failures::const_iterator it = failures_.begin(); it != itEnd; ++it) {
|
||||||
const Failure& failure = *it;
|
const Failure& failure = *it;
|
||||||
std::string indent(failure.nestingLevel_ * 2, ' ');
|
JSONCPP_STRING indent(failure.nestingLevel_ * 2, ' ');
|
||||||
if (failure.file_) {
|
if (failure.file_) {
|
||||||
printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_);
|
printf("%s%s(%d): ", indent.c_str(), failure.file_, failure.line_);
|
||||||
}
|
}
|
||||||
@@ -173,19 +173,19 @@ void TestResult::printFailure(bool printTestName) const {
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
if (!failure.message_.empty()) {
|
if (!failure.message_.empty()) {
|
||||||
std::string reindented = indentText(failure.message_, indent + " ");
|
JSONCPP_STRING reindented = indentText(failure.message_, indent + " ");
|
||||||
printf("%s\n", reindented.c_str());
|
printf("%s\n", reindented.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string TestResult::indentText(const std::string& text,
|
JSONCPP_STRING TestResult::indentText(const JSONCPP_STRING& text,
|
||||||
const std::string& indent) {
|
const JSONCPP_STRING& indent) {
|
||||||
std::string reindented;
|
JSONCPP_STRING reindented;
|
||||||
std::string::size_type lastIndex = 0;
|
JSONCPP_STRING::size_type lastIndex = 0;
|
||||||
while (lastIndex < text.size()) {
|
while (lastIndex < text.size()) {
|
||||||
std::string::size_type nextIndex = text.find('\n', lastIndex);
|
JSONCPP_STRING::size_type nextIndex = text.find('\n', lastIndex);
|
||||||
if (nextIndex == std::string::npos) {
|
if (nextIndex == JSONCPP_STRING::npos) {
|
||||||
nextIndex = text.size() - 1;
|
nextIndex = text.size() - 1;
|
||||||
}
|
}
|
||||||
reindented += indent;
|
reindented += indent;
|
||||||
@@ -195,7 +195,7 @@ std::string TestResult::indentText(const std::string& text,
|
|||||||
return reindented;
|
return reindented;
|
||||||
}
|
}
|
||||||
|
|
||||||
TestResult& TestResult::addToLastFailure(const std::string& message) {
|
TestResult& TestResult::addToLastFailure(const JSONCPP_STRING& message) {
|
||||||
if (messageTarget_ != 0) {
|
if (messageTarget_ != 0) {
|
||||||
messageTarget_->message_ += message;
|
messageTarget_->message_ += message;
|
||||||
}
|
}
|
||||||
@@ -240,9 +240,9 @@ unsigned int Runner::testCount() const {
|
|||||||
return static_cast<unsigned int>(tests_.size());
|
return static_cast<unsigned int>(tests_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Runner::testNameAt(unsigned int index) const {
|
JSONCPP_STRING Runner::testNameAt(unsigned int index) const {
|
||||||
TestCase* test = tests_[index]();
|
TestCase* test = tests_[index]();
|
||||||
std::string name = test->testName();
|
JSONCPP_STRING name = test->testName();
|
||||||
delete test;
|
delete test;
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ bool Runner::runAllTest(bool printSummary) const {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Runner::testIndex(const std::string& testName,
|
bool Runner::testIndex(const JSONCPP_STRING& testName,
|
||||||
unsigned int& indexOut) const {
|
unsigned int& indexOut) const {
|
||||||
unsigned int count = testCount();
|
unsigned int count = testCount();
|
||||||
for (unsigned int index = 0; index < count; ++index) {
|
for (unsigned int index = 0; index < count; ++index) {
|
||||||
@@ -323,10 +323,10 @@ void Runner::listTests() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int Runner::runCommandLine(int argc, const char* argv[]) const {
|
int Runner::runCommandLine(int argc, const char* argv[]) const {
|
||||||
// typedef std::deque<std::string> TestNames;
|
// typedef std::deque<JSONCPP_STRING> TestNames;
|
||||||
Runner subrunner;
|
Runner subrunner;
|
||||||
for (int index = 1; index < argc; ++index) {
|
for (int index = 1; index < argc; ++index) {
|
||||||
std::string opt = argv[index];
|
JSONCPP_STRING opt = argv[index];
|
||||||
if (opt == "--list-tests") {
|
if (opt == "--list-tests") {
|
||||||
listTests();
|
listTests();
|
||||||
return 0;
|
return 0;
|
||||||
@@ -426,9 +426,23 @@ void Runner::printUsage(const char* appName) {
|
|||||||
// Assertion functions
|
// Assertion functions
|
||||||
// //////////////////////////////////////////////////////////////////
|
// //////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
JSONCPP_STRING ToJsonString(const char* toConvert) {
|
||||||
|
return JSONCPP_STRING(toConvert);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONCPP_STRING ToJsonString(JSONCPP_STRING in) {
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
JSONCPP_STRING ToJsonString(std::string in) {
|
||||||
|
return JSONCPP_STRING(in.data(), in.data() + in.length());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TestResult& checkStringEqual(TestResult& result,
|
TestResult& checkStringEqual(TestResult& result,
|
||||||
const std::string& expected,
|
const JSONCPP_STRING& expected,
|
||||||
const std::string& actual,
|
const JSONCPP_STRING& actual,
|
||||||
const char* file,
|
const char* file,
|
||||||
unsigned int line,
|
unsigned int line,
|
||||||
const char* expr) {
|
const char* expr) {
|
||||||
|
@@ -32,8 +32,8 @@ class Failure {
|
|||||||
public:
|
public:
|
||||||
const char* file_;
|
const char* file_;
|
||||||
unsigned int line_;
|
unsigned int line_;
|
||||||
std::string expr_;
|
JSONCPP_STRING expr_;
|
||||||
std::string message_;
|
JSONCPP_STRING message_;
|
||||||
unsigned int nestingLevel_;
|
unsigned int nestingLevel_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ public:
|
|||||||
/// \internal Implementation detail for predicate macros
|
/// \internal Implementation detail for predicate macros
|
||||||
PredicateContext* predicateStackTail_;
|
PredicateContext* predicateStackTail_;
|
||||||
|
|
||||||
void setTestName(const std::string& name);
|
void setTestName(const JSONCPP_STRING& name);
|
||||||
|
|
||||||
/// Adds an assertion failure.
|
/// Adds an assertion failure.
|
||||||
TestResult&
|
TestResult&
|
||||||
@@ -82,7 +82,7 @@ public:
|
|||||||
|
|
||||||
// Generic operator that will work with anything ostream can deal with.
|
// Generic operator that will work with anything ostream can deal with.
|
||||||
template <typename T> TestResult& operator<<(const T& value) {
|
template <typename T> TestResult& operator<<(const T& value) {
|
||||||
std::ostringstream oss;
|
JSONCPP_OSTRINGSTREAM oss;
|
||||||
oss.precision(16);
|
oss.precision(16);
|
||||||
oss.setf(std::ios_base::floatfield);
|
oss.setf(std::ios_base::floatfield);
|
||||||
oss << value;
|
oss << value;
|
||||||
@@ -96,19 +96,19 @@ public:
|
|||||||
TestResult& operator<<(Json::UInt64 value);
|
TestResult& operator<<(Json::UInt64 value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TestResult& addToLastFailure(const std::string& message);
|
TestResult& addToLastFailure(const JSONCPP_STRING& message);
|
||||||
unsigned int getAssertionNestingLevel() const;
|
unsigned int getAssertionNestingLevel() const;
|
||||||
/// Adds a failure or a predicate context
|
/// Adds a failure or a predicate context
|
||||||
void addFailureInfo(const char* file,
|
void addFailureInfo(const char* file,
|
||||||
unsigned int line,
|
unsigned int line,
|
||||||
const char* expr,
|
const char* expr,
|
||||||
unsigned int nestingLevel);
|
unsigned int nestingLevel);
|
||||||
static std::string indentText(const std::string& text,
|
static JSONCPP_STRING indentText(const JSONCPP_STRING& text,
|
||||||
const std::string& indent);
|
const JSONCPP_STRING& indent);
|
||||||
|
|
||||||
typedef std::deque<Failure> Failures;
|
typedef std::deque<Failure> Failures;
|
||||||
Failures failures_;
|
Failures failures_;
|
||||||
std::string name_;
|
JSONCPP_STRING name_;
|
||||||
PredicateContext rootPredicateNode_;
|
PredicateContext rootPredicateNode_;
|
||||||
PredicateContext::Id lastUsedPredicateId_;
|
PredicateContext::Id lastUsedPredicateId_;
|
||||||
/// Failure which is the target of the messages added using operator <<
|
/// Failure which is the target of the messages added using operator <<
|
||||||
@@ -155,7 +155,7 @@ public:
|
|||||||
unsigned int testCount() const;
|
unsigned int testCount() const;
|
||||||
|
|
||||||
/// Returns the name of the test case at the specified index
|
/// Returns the name of the test case at the specified index
|
||||||
std::string testNameAt(unsigned int index) const;
|
JSONCPP_STRING testNameAt(unsigned int index) const;
|
||||||
|
|
||||||
/// Runs the test case at the specified index using the specified TestResult
|
/// Runs the test case at the specified index using the specified TestResult
|
||||||
void runTestAt(unsigned int index, TestResult& result) const;
|
void runTestAt(unsigned int index, TestResult& result) const;
|
||||||
@@ -168,7 +168,7 @@ private: // prevents copy construction and assignment
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void listTests() const;
|
void listTests() const;
|
||||||
bool testIndex(const std::string& testName, unsigned int& index) const;
|
bool testIndex(const JSONCPP_STRING& testName, unsigned int& index) const;
|
||||||
static void preventDialogOnCrash();
|
static void preventDialogOnCrash();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -191,9 +191,15 @@ TestResult& checkEqual(TestResult& result,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONCPP_STRING ToJsonString(const char* toConvert);
|
||||||
|
JSONCPP_STRING ToJsonString(JSONCPP_STRING in);
|
||||||
|
#if JSONCPP_USING_SECURE_MEMORY
|
||||||
|
JSONCPP_STRING ToJsonString(std::string in);
|
||||||
|
#endif
|
||||||
|
|
||||||
TestResult& checkStringEqual(TestResult& result,
|
TestResult& checkStringEqual(TestResult& result,
|
||||||
const std::string& expected,
|
const JSONCPP_STRING& expected,
|
||||||
const std::string& actual,
|
const JSONCPP_STRING& actual,
|
||||||
const char* file,
|
const char* file,
|
||||||
unsigned int line,
|
unsigned int line,
|
||||||
const char* expr);
|
const char* expr);
|
||||||
@@ -235,8 +241,8 @@ TestResult& checkStringEqual(TestResult& result,
|
|||||||
/// \brief Asserts that two values are equals.
|
/// \brief Asserts that two values are equals.
|
||||||
#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \
|
#define JSONTEST_ASSERT_STRING_EQUAL(expected, actual) \
|
||||||
JsonTest::checkStringEqual(*result_, \
|
JsonTest::checkStringEqual(*result_, \
|
||||||
std::string(expected), \
|
JsonTest::ToJsonString(expected), \
|
||||||
std::string(actual), \
|
JsonTest::ToJsonString(actual), \
|
||||||
__FILE__, \
|
__FILE__, \
|
||||||
__LINE__, \
|
__LINE__, \
|
||||||
#expected " == " #actual)
|
#expected " == " #actual)
|
||||||
@@ -265,8 +271,8 @@ TestResult& checkStringEqual(TestResult& result,
|
|||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
public: /* overidden from TestCase */ \
|
public: /* overidden from TestCase */ \
|
||||||
virtual const char* testName() const { return #FixtureType "/" #name; } \
|
const char* testName() const JSONCPP_OVERRIDE { return #FixtureType "/" #name; } \
|
||||||
virtual void runTestCase(); \
|
void runTestCase() JSONCPP_OVERRIDE; \
|
||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
void Test##FixtureType##name::runTestCase()
|
void Test##FixtureType##name::runTestCase()
|
||||||
|
@@ -6,8 +6,11 @@
|
|||||||
#include "jsontest.h"
|
#include "jsontest.h"
|
||||||
#include <json/config.h>
|
#include <json/config.h>
|
||||||
#include <json/json.h>
|
#include <json/json.h>
|
||||||
#include <stdexcept>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <limits>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
// Make numeric limits more convenient to talk about.
|
// Make numeric limits more convenient to talk about.
|
||||||
// Assumes int type in 32 bits.
|
// Assumes int type in 32 bits.
|
||||||
@@ -36,7 +39,7 @@ static inline double uint64ToDouble(Json::UInt64 value) {
|
|||||||
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#else // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
static inline double uint64ToDouble(Json::UInt64 value) {
|
static inline double uint64ToDouble(Json::UInt64 value) {
|
||||||
return static_cast<double>(Json::Int64(value / 2)) * 2.0 +
|
return static_cast<double>(Json::Int64(value / 2)) * 2.0 +
|
||||||
Json::Int64(value & 1);
|
static_cast<double>(Json::Int64(value & 1));
|
||||||
}
|
}
|
||||||
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
|
||||||
|
|
||||||
@@ -99,21 +102,21 @@ struct ValueTest : JsonTest::TestCase {
|
|||||||
|
|
||||||
/// Normalize the representation of floating-point number by stripped leading
|
/// Normalize the representation of floating-point number by stripped leading
|
||||||
/// 0 in exponent.
|
/// 0 in exponent.
|
||||||
static std::string normalizeFloatingPointStr(const std::string& s);
|
static JSONCPP_STRING normalizeFloatingPointStr(const JSONCPP_STRING& s);
|
||||||
};
|
};
|
||||||
|
|
||||||
std::string ValueTest::normalizeFloatingPointStr(const std::string& s) {
|
JSONCPP_STRING ValueTest::normalizeFloatingPointStr(const JSONCPP_STRING& s) {
|
||||||
std::string::size_type index = s.find_last_of("eE");
|
JSONCPP_STRING::size_type index = s.find_last_of("eE");
|
||||||
if (index != std::string::npos) {
|
if (index != JSONCPP_STRING::npos) {
|
||||||
std::string::size_type hasSign =
|
JSONCPP_STRING::size_type hasSign =
|
||||||
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
(s[index + 1] == '+' || s[index + 1] == '-') ? 1 : 0;
|
||||||
std::string::size_type exponentStartIndex = index + 1 + hasSign;
|
JSONCPP_STRING::size_type exponentStartIndex = index + 1 + hasSign;
|
||||||
std::string normalized = s.substr(0, exponentStartIndex);
|
JSONCPP_STRING normalized = s.substr(0, exponentStartIndex);
|
||||||
std::string::size_type indexDigit =
|
JSONCPP_STRING::size_type indexDigit =
|
||||||
s.find_first_not_of('0', exponentStartIndex);
|
s.find_first_not_of('0', exponentStartIndex);
|
||||||
std::string exponent = "0";
|
JSONCPP_STRING exponent = "0";
|
||||||
if (indexDigit !=
|
if (indexDigit !=
|
||||||
std::string::npos) // There is an exponent different from 0
|
JSONCPP_STRING::npos) // There is an exponent different from 0
|
||||||
{
|
{
|
||||||
exponent = s.substr(indexDigit);
|
exponent = s.substr(indexDigit);
|
||||||
}
|
}
|
||||||
@@ -258,6 +261,20 @@ JSONTEST_FIXTURE(ValueTest, arrays) {
|
|||||||
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
|
JSONTEST_ASSERT_EQUAL(Json::Value(17), got);
|
||||||
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
|
JSONTEST_ASSERT_EQUAL(false, array1_.removeIndex(2, &got)); // gone now
|
||||||
}
|
}
|
||||||
|
JSONTEST_FIXTURE(ValueTest, arrayIssue252)
|
||||||
|
{
|
||||||
|
int count = 5;
|
||||||
|
Json::Value root;
|
||||||
|
Json::Value item;
|
||||||
|
root["array"] = Json::Value::nullRef;
|
||||||
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
item["a"] = i;
|
||||||
|
item["b"] = i;
|
||||||
|
root["array"][i] = item;
|
||||||
|
}
|
||||||
|
//JSONTEST_ASSERT_EQUAL(5, root["array"].size());
|
||||||
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE(ValueTest, null) {
|
JSONTEST_FIXTURE(ValueTest, null) {
|
||||||
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());
|
JSONTEST_ASSERT_EQUAL(Json::nullValue, null_.type());
|
||||||
@@ -462,7 +479,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
|
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(false, val.asBool());
|
JSONTEST_ASSERT_EQUAL(false, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
|
JSONTEST_ASSERT_STRING_EQUAL("0.0", val.asString());
|
||||||
|
|
||||||
// Zero (signed constructor arg)
|
// Zero (signed constructor arg)
|
||||||
val = Json::Value(0);
|
val = Json::Value(0);
|
||||||
@@ -546,7 +563,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
|
JSONTEST_ASSERT_EQUAL(0.0, val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(0.0, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(false, val.asBool());
|
JSONTEST_ASSERT_EQUAL(false, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("0", val.asString());
|
JSONTEST_ASSERT_STRING_EQUAL("0.0", val.asString());
|
||||||
|
|
||||||
// 2^20 (signed constructor arg)
|
// 2^20 (signed constructor arg)
|
||||||
val = Json::Value(1 << 20);
|
val = Json::Value(1 << 20);
|
||||||
@@ -629,8 +646,8 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
|
JSONTEST_ASSERT_EQUAL((1 << 20), val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
|
JSONTEST_ASSERT_EQUAL((1 << 20), val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1048576",
|
JSONTEST_ASSERT_STRING_EQUAL("1048576.0",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// -2^20
|
// -2^20
|
||||||
val = Json::Value(-(1 << 20));
|
val = Json::Value(-(1 << 20));
|
||||||
@@ -870,8 +887,8 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble());
|
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat());
|
JSONTEST_ASSERT_EQUAL((Json::Int64(1) << 40), val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1099511627776",
|
JSONTEST_ASSERT_STRING_EQUAL("1099511627776.0",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// -2^40
|
// -2^40
|
||||||
val = Json::Value(-(Json::Int64(1) << 40));
|
val = Json::Value(-(Json::Int64(1) << 40));
|
||||||
@@ -946,7 +963,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
val.asFloat());
|
val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18",
|
JSONTEST_ASSERT_STRING_EQUAL("9.2233720368547758e+18",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// int64 min
|
// int64 min
|
||||||
val = Json::Value(Json::Int64(kint64min));
|
val = Json::Value(Json::Int64(kint64min));
|
||||||
@@ -994,7 +1011,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(-9223372036854775808.0, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18",
|
JSONTEST_ASSERT_STRING_EQUAL("-9.2233720368547758e+18",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// 10^19
|
// 10^19
|
||||||
const Json::UInt64 ten_to_19 = static_cast<Json::UInt64>(1e19);
|
const Json::UInt64 ten_to_19 = static_cast<Json::UInt64>(1e19);
|
||||||
@@ -1041,7 +1058,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(1e19, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(1e19, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1e+19",
|
JSONTEST_ASSERT_STRING_EQUAL("1e+19",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// uint64 max
|
// uint64 max
|
||||||
val = Json::Value(Json::UInt64(kuint64max));
|
val = Json::Value(Json::UInt64(kuint64max));
|
||||||
@@ -1085,7 +1102,7 @@ JSONTEST_FIXTURE(ValueTest, integers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
|
JSONTEST_ASSERT_EQUAL(18446744073709551616.0, val.asFloat());
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19",
|
JSONTEST_ASSERT_STRING_EQUAL("1.8446744073709552e+19",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1175,7 +1192,7 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
|
|||||||
#endif
|
#endif
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_EQUAL("2147483647.5",
|
JSONTEST_ASSERT_EQUAL("2147483647.5",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// A bit under int32 min
|
// A bit under int32 min
|
||||||
val = Json::Value(kint32min - 0.5);
|
val = Json::Value(kint32min - 0.5);
|
||||||
@@ -1199,11 +1216,11 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
|
|||||||
JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble());
|
JSONTEST_ASSERT_EQUAL(-2147483648.5, val.asDouble());
|
||||||
JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat());
|
JSONTEST_ASSERT_EQUAL(float(-2147483648.5), val.asFloat());
|
||||||
#ifdef JSON_HAS_INT64
|
#ifdef JSON_HAS_INT64
|
||||||
JSONTEST_ASSERT_EQUAL(-Json::Int64(1) << 31, val.asLargestInt());
|
JSONTEST_ASSERT_EQUAL(-(Json::Int64(1) << 31), val.asLargestInt());
|
||||||
#endif
|
#endif
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_EQUAL("-2147483648.5",
|
JSONTEST_ASSERT_EQUAL("-2147483648.5",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// A bit over uint32 max
|
// A bit over uint32 max
|
||||||
val = Json::Value(kuint32max + 0.5);
|
val = Json::Value(kuint32max + 0.5);
|
||||||
@@ -1233,29 +1250,29 @@ JSONTEST_FIXTURE(ValueTest, nonIntegers) {
|
|||||||
#endif
|
#endif
|
||||||
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
JSONTEST_ASSERT_EQUAL(true, val.asBool());
|
||||||
JSONTEST_ASSERT_EQUAL("4294967295.5",
|
JSONTEST_ASSERT_EQUAL("4294967295.5",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
val = Json::Value(1.2345678901234);
|
val = Json::Value(1.2345678901234);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001",
|
JSONTEST_ASSERT_STRING_EQUAL("1.2345678901234001",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// A 16-digit floating point number.
|
// A 16-digit floating point number.
|
||||||
val = Json::Value(2199023255552000.0f);
|
val = Json::Value(2199023255552000.0f);
|
||||||
JSONTEST_ASSERT_EQUAL(float(2199023255552000), val.asFloat());
|
JSONTEST_ASSERT_EQUAL(float(2199023255552000.0f), val.asFloat());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("2199023255552000",
|
JSONTEST_ASSERT_STRING_EQUAL("2199023255552000.0",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// A very large floating point number.
|
// A very large floating point number.
|
||||||
val = Json::Value(3.402823466385289e38);
|
val = Json::Value(3.402823466385289e38);
|
||||||
JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat());
|
JSONTEST_ASSERT_EQUAL(float(3.402823466385289e38), val.asFloat());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("3.402823466385289e+38",
|
JSONTEST_ASSERT_STRING_EQUAL("3.402823466385289e+38",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
|
|
||||||
// An even larger floating point number.
|
// An even larger floating point number.
|
||||||
val = Json::Value(1.2345678e300);
|
val = Json::Value(1.2345678e300);
|
||||||
JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble());
|
JSONTEST_ASSERT_EQUAL(double(1.2345678e300), val.asDouble());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("1.2345678e+300",
|
JSONTEST_ASSERT_STRING_EQUAL("1.2345678e+300",
|
||||||
normalizeFloatingPointStr(val.asString()));
|
normalizeFloatingPointStr(JsonTest::ToJsonString(val.asString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
void ValueTest::checkConstMemberCount(const Json::Value& value,
|
void ValueTest::checkConstMemberCount(const Json::Value& value,
|
||||||
@@ -1521,7 +1538,7 @@ JSONTEST_FIXTURE(ValueTest, offsetAccessors) {
|
|||||||
JSONTEST_FIXTURE(ValueTest, StaticString) {
|
JSONTEST_FIXTURE(ValueTest, StaticString) {
|
||||||
char mutant[] = "hello";
|
char mutant[] = "hello";
|
||||||
Json::StaticString ss(mutant);
|
Json::StaticString ss(mutant);
|
||||||
std::string regular(mutant);
|
JSONCPP_STRING regular(mutant);
|
||||||
mutant[1] = 'a';
|
mutant[1] = 'a';
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("hallo", ss.c_str());
|
JSONTEST_ASSERT_STRING_EQUAL("hallo", ss.c_str());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("hello", regular.c_str());
|
JSONTEST_ASSERT_STRING_EQUAL("hello", regular.c_str());
|
||||||
@@ -1543,15 +1560,15 @@ JSONTEST_FIXTURE(ValueTest, StaticString) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
||||||
Json::Value val; // fill val
|
Json::Value val; // fill val
|
||||||
val.setComment("// this comment should appear before", Json::commentBefore);
|
val.setComment(JSONCPP_STRING("// this comment should appear before"), Json::commentBefore);
|
||||||
Json::StreamWriterBuilder wbuilder;
|
Json::StreamWriterBuilder wbuilder;
|
||||||
wbuilder.settings_["commentStyle"] = "All";
|
wbuilder.settings_["commentStyle"] = "All";
|
||||||
{
|
{
|
||||||
char const expected[] = "// this comment should appear before\nnull";
|
char const expected[] = "// this comment should appear before\nnull";
|
||||||
std::string result = Json::writeString(wbuilder, val);
|
JSONCPP_STRING result = Json::writeString(wbuilder, val);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
std::string res2 = val.toStyledString();
|
JSONCPP_STRING res2 = val.toStyledString();
|
||||||
std::string exp2 = "\n";
|
JSONCPP_STRING exp2 = "\n";
|
||||||
exp2 += expected;
|
exp2 += expected;
|
||||||
exp2 += "\n";
|
exp2 += "\n";
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
||||||
@@ -1560,10 +1577,10 @@ JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
|||||||
val.swapPayload(other);
|
val.swapPayload(other);
|
||||||
{
|
{
|
||||||
char const expected[] = "// this comment should appear before\n\"hello\"";
|
char const expected[] = "// this comment should appear before\n\"hello\"";
|
||||||
std::string result = Json::writeString(wbuilder, val);
|
JSONCPP_STRING result = Json::writeString(wbuilder, val);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
std::string res2 = val.toStyledString();
|
JSONCPP_STRING res2 = val.toStyledString();
|
||||||
std::string exp2 = "\n";
|
JSONCPP_STRING exp2 = "\n";
|
||||||
exp2 += expected;
|
exp2 += expected;
|
||||||
exp2 += "\n";
|
exp2 += "\n";
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
||||||
@@ -1574,10 +1591,10 @@ JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
|||||||
// Assignment over-writes comments.
|
// Assignment over-writes comments.
|
||||||
{
|
{
|
||||||
char const expected[] = "\"hello\"";
|
char const expected[] = "\"hello\"";
|
||||||
std::string result = Json::writeString(wbuilder, val);
|
JSONCPP_STRING result = Json::writeString(wbuilder, val);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
std::string res2 = val.toStyledString();
|
JSONCPP_STRING res2 = val.toStyledString();
|
||||||
std::string exp2 = "";
|
JSONCPP_STRING exp2 = "";
|
||||||
exp2 += expected;
|
exp2 += expected;
|
||||||
exp2 += "\n";
|
exp2 += "\n";
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
JSONTEST_ASSERT_STRING_EQUAL(exp2, res2);
|
||||||
@@ -1586,7 +1603,7 @@ JSONTEST_FIXTURE(ValueTest, CommentBefore) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE(ValueTest, zeroes) {
|
JSONTEST_FIXTURE(ValueTest, zeroes) {
|
||||||
char const cstr[] = "h\0i";
|
char const cstr[] = "h\0i";
|
||||||
std::string binary(cstr, sizeof(cstr)); // include trailing 0
|
JSONCPP_STRING binary(cstr, sizeof(cstr)); // include trailing 0
|
||||||
JSONTEST_ASSERT_EQUAL(4U, binary.length());
|
JSONTEST_ASSERT_EQUAL(4U, binary.length());
|
||||||
Json::StreamWriterBuilder b;
|
Json::StreamWriterBuilder b;
|
||||||
{
|
{
|
||||||
@@ -1614,7 +1631,7 @@ JSONTEST_FIXTURE(ValueTest, zeroes) {
|
|||||||
|
|
||||||
JSONTEST_FIXTURE(ValueTest, zeroesInKeys) {
|
JSONTEST_FIXTURE(ValueTest, zeroesInKeys) {
|
||||||
char const cstr[] = "h\0i";
|
char const cstr[] = "h\0i";
|
||||||
std::string binary(cstr, sizeof(cstr)); // include trailing 0
|
JSONCPP_STRING binary(cstr, sizeof(cstr)); // include trailing 0
|
||||||
JSONTEST_ASSERT_EQUAL(4U, binary.length());
|
JSONTEST_ASSERT_EQUAL(4U, binary.length());
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
@@ -1638,6 +1655,63 @@ JSONTEST_FIXTURE(ValueTest, zeroesInKeys) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(ValueTest, specialFloats) {
|
||||||
|
Json::StreamWriterBuilder b;
|
||||||
|
b.settings_["useSpecialFloats"] = true;
|
||||||
|
|
||||||
|
Json::Value v = std::numeric_limits<double>::quiet_NaN();
|
||||||
|
JSONCPP_STRING expected = "NaN";
|
||||||
|
JSONCPP_STRING result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
v = std::numeric_limits<double>::infinity();
|
||||||
|
expected = "Infinity";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
v = -std::numeric_limits<double>::infinity();
|
||||||
|
expected = "-Infinity";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(ValueTest, precision) {
|
||||||
|
Json::StreamWriterBuilder b;
|
||||||
|
b.settings_["precision"] = 5;
|
||||||
|
|
||||||
|
Json::Value v = 100.0/3;
|
||||||
|
JSONCPP_STRING expected = "33.333";
|
||||||
|
JSONCPP_STRING result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
v = 0.25000000;
|
||||||
|
expected = "0.25";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
v = 0.2563456;
|
||||||
|
expected = "0.25635";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
b.settings_["precision"] = 1;
|
||||||
|
expected = "0.3";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
b.settings_["precision"] = 17;
|
||||||
|
v = 1234857476305.256345694873740545068;
|
||||||
|
expected = "1234857476305.2563";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
|
||||||
|
b.settings_["precision"] = 24;
|
||||||
|
v = 0.256345694873740545068;
|
||||||
|
expected = "0.25634569487374054";
|
||||||
|
result = Json::writeString(b, v);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, result);
|
||||||
|
}
|
||||||
|
|
||||||
struct WriterTest : JsonTest::TestCase {};
|
struct WriterTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) {
|
JSONTEST_FIXTURE(WriterTest, dropNullPlaceholders) {
|
||||||
@@ -1661,15 +1735,15 @@ JSONTEST_FIXTURE(StreamWriterTest, dropNullPlaceholders) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
JSONTEST_FIXTURE(StreamWriterTest, writeZeroes) {
|
JSONTEST_FIXTURE(StreamWriterTest, writeZeroes) {
|
||||||
std::string binary("hi", 3); // include trailing 0
|
JSONCPP_STRING binary("hi", 3); // include trailing 0
|
||||||
JSONTEST_ASSERT_EQUAL(3, binary.length());
|
JSONTEST_ASSERT_EQUAL(3, binary.length());
|
||||||
std::string expected("\"hi\\u0000\""); // unicoded zero
|
JSONCPP_STRING expected("\"hi\\u0000\""); // unicoded zero
|
||||||
Json::StreamWriterBuilder b;
|
Json::StreamWriterBuilder b;
|
||||||
{
|
{
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
root = binary;
|
root = binary;
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString());
|
JSONTEST_ASSERT_STRING_EQUAL(binary, root.asString());
|
||||||
std::string out = Json::writeString(b, root);
|
JSONCPP_STRING out = Json::writeString(b, root);
|
||||||
JSONTEST_ASSERT_EQUAL(expected.size(), out.size());
|
JSONTEST_ASSERT_EQUAL(expected.size(), out.size());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, out);
|
JSONTEST_ASSERT_STRING_EQUAL(expected, out);
|
||||||
}
|
}
|
||||||
@@ -1677,7 +1751,7 @@ JSONTEST_FIXTURE(StreamWriterTest, writeZeroes) {
|
|||||||
Json::Value root;
|
Json::Value root;
|
||||||
root["top"] = binary;
|
root["top"] = binary;
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(binary, root["top"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL(binary, root["top"].asString());
|
||||||
std::string out = Json::writeString(b, root["top"]);
|
JSONCPP_STRING out = Json::writeString(b, root["top"]);
|
||||||
JSONTEST_ASSERT_STRING_EQUAL(expected, out);
|
JSONTEST_ASSERT_STRING_EQUAL(expected, out);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1778,7 +1852,7 @@ struct CharReaderTest : JsonTest::TestCase {};
|
|||||||
JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrors) {
|
JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrors) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] = "{ \"property\" : \"value\" }";
|
char const doc[] = "{ \"property\" : \"value\" }";
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
@@ -1792,7 +1866,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrors) {
|
|||||||
JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
"{ \"property\" : [\"value\", \"value2\"], \"obj\" : "
|
"{ \"property\" : [\"value\", \"value2\"], \"obj\" : "
|
||||||
@@ -1809,7 +1883,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithNoErrorsTestingOffsets) {
|
|||||||
JSONTEST_FIXTURE(CharReaderTest, parseWithOneError) {
|
JSONTEST_FIXTURE(CharReaderTest, parseWithOneError) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
"{ \"property\" :: \"value\" }";
|
"{ \"property\" :: \"value\" }";
|
||||||
@@ -1826,7 +1900,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithOneError) {
|
|||||||
JSONTEST_FIXTURE(CharReaderTest, parseChineseWithOneError) {
|
JSONTEST_FIXTURE(CharReaderTest, parseChineseWithOneError) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
"{ \"pr佐藤erty\" :: \"value\" }";
|
"{ \"pr佐藤erty\" :: \"value\" }";
|
||||||
@@ -1843,7 +1917,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseChineseWithOneError) {
|
|||||||
JSONTEST_FIXTURE(CharReaderTest, parseWithDetailError) {
|
JSONTEST_FIXTURE(CharReaderTest, parseWithDetailError) {
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
"{ \"property\" : \"v\\alue\" }";
|
"{ \"property\" : \"v\\alue\" }";
|
||||||
@@ -1865,7 +1939,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
|
|||||||
{
|
{
|
||||||
b.settings_["stackLimit"] = 2;
|
b.settings_["stackLimit"] = 2;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1877,7 +1951,7 @@ JSONTEST_FIXTURE(CharReaderTest, parseWithStackLimit) {
|
|||||||
{
|
{
|
||||||
b.settings_["stackLimit"] = 1;
|
b.settings_["stackLimit"] = 1;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
JSONTEST_ASSERT_THROWS(reader->parse(
|
JSONTEST_ASSERT_THROWS(reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs));
|
&root, &errs));
|
||||||
@@ -1895,7 +1969,7 @@ JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) {
|
|||||||
{
|
{
|
||||||
b.strictMode(&b.settings_);
|
b.strictMode(&b.settings_);
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1911,7 +1985,7 @@ JSONTEST_FIXTURE(CharReaderStrictModeTest, dupKeys) {
|
|||||||
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
struct CharReaderFailIfExtraTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
||||||
// This is interpretted as a string value followed by a colon.
|
// This is interpreted as a string value followed by a colon.
|
||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
char const doc[] =
|
char const doc[] =
|
||||||
@@ -1919,7 +1993,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
|||||||
{
|
{
|
||||||
b.settings_["failIfExtra"] = false;
|
b.settings_["failIfExtra"] = false;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1931,7 +2005,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
|||||||
{
|
{
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1946,7 +2020,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue164) {
|
|||||||
b.settings_["failIfExtra"] = false;
|
b.settings_["failIfExtra"] = false;
|
||||||
b.strictMode(&b.settings_);
|
b.strictMode(&b.settings_);
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1966,7 +2040,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, issue107) {
|
|||||||
"1:2:3";
|
"1:2:3";
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -1986,7 +2060,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterObject) {
|
|||||||
"{ \"property\" : \"value\" } //trailing\n//comment\n";
|
"{ \"property\" : \"value\" } //trailing\n//comment\n";
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -2003,7 +2077,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterArray) {
|
|||||||
"[ \"property\" , \"value\" ] //trailing\n//comment\n";
|
"[ \"property\" , \"value\" ] //trailing\n//comment\n";
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -2019,7 +2093,7 @@ JSONTEST_FIXTURE(CharReaderFailIfExtraTest, commentAfterBool) {
|
|||||||
" true /*trailing\ncomment*/";
|
" true /*trailing\ncomment*/";
|
||||||
b.settings_["failIfExtra"] = true;
|
b.settings_["failIfExtra"] = true;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
bool ok = reader->parse(
|
bool ok = reader->parse(
|
||||||
doc, doc + std::strlen(doc),
|
doc, doc + std::strlen(doc),
|
||||||
&root, &errs);
|
&root, &errs);
|
||||||
@@ -2034,7 +2108,7 @@ JSONTEST_FIXTURE(CharReaderAllowDropNullTest, issue178) {
|
|||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
b.settings_["allowDroppedNullPlaceholders"] = true;
|
b.settings_["allowDroppedNullPlaceholders"] = true;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
{
|
{
|
||||||
char const doc[] = "{\"a\":,\"b\":true}";
|
char const doc[] = "{\"a\":,\"b\":true}";
|
||||||
@@ -2186,7 +2260,7 @@ JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) {
|
|||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
b.settings_["allowSingleQuotes"] = true;
|
b.settings_["allowSingleQuotes"] = true;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
{
|
{
|
||||||
char const doc[] = "{'a':true,\"b\":true}";
|
char const doc[] = "{'a':true,\"b\":true}";
|
||||||
@@ -2210,6 +2284,7 @@ JSONTEST_FIXTURE(CharReaderAllowSingleQuotesTest, issue182) {
|
|||||||
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
|
struct CharReaderAllowZeroesTest : JsonTest::TestCase {};
|
||||||
@@ -2218,7 +2293,7 @@ JSONTEST_FIXTURE(CharReaderAllowZeroesTest, issue176) {
|
|||||||
Json::CharReaderBuilder b;
|
Json::CharReaderBuilder b;
|
||||||
b.settings_["allowSingleQuotes"] = true;
|
b.settings_["allowSingleQuotes"] = true;
|
||||||
Json::Value root;
|
Json::Value root;
|
||||||
std::string errs;
|
JSONCPP_STRING errs;
|
||||||
Json::CharReader* reader(b.newCharReader());
|
Json::CharReader* reader(b.newCharReader());
|
||||||
{
|
{
|
||||||
char const doc[] = "{'a':true,\"b\":true}";
|
char const doc[] = "{'a':true,\"b\":true}";
|
||||||
@@ -2242,6 +2317,82 @@ JSONTEST_FIXTURE(CharReaderAllowZeroesTest, issue176) {
|
|||||||
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("x", root["a"].asString());
|
||||||
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
JSONTEST_ASSERT_STRING_EQUAL("y", root["b"].asString());
|
||||||
}
|
}
|
||||||
|
delete reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CharReaderAllowSpecialFloatsTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(CharReaderAllowSpecialFloatsTest, issue209) {
|
||||||
|
Json::CharReaderBuilder b;
|
||||||
|
b.settings_["allowSpecialFloats"] = true;
|
||||||
|
Json::Value root;
|
||||||
|
JSONCPP_STRING errs;
|
||||||
|
Json::CharReader* reader(b.newCharReader());
|
||||||
|
{
|
||||||
|
char const doc[] = "{\"a\":NaN,\"b\":Infinity,\"c\":-Infinity}";
|
||||||
|
bool ok = reader->parse(
|
||||||
|
doc, doc + std::strlen(doc),
|
||||||
|
&root, &errs);
|
||||||
|
JSONTEST_ASSERT(ok);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
|
JSONTEST_ASSERT_EQUAL(3u, root.size());
|
||||||
|
double n = root["a"].asDouble();
|
||||||
|
JSONTEST_ASSERT(n != n);
|
||||||
|
JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), root.get("b", 0.0));
|
||||||
|
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(), root.get("c", 0.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TestData {
|
||||||
|
int line;
|
||||||
|
bool ok;
|
||||||
|
JSONCPP_STRING in;
|
||||||
|
};
|
||||||
|
const TestData test_data[] = {
|
||||||
|
{__LINE__, 1, "{\"a\":9}"},
|
||||||
|
{__LINE__, 0, "{\"a\":0Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":1Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":9Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":0nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":1nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":9nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":.nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":9nfinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":-nfinity}"},
|
||||||
|
{__LINE__, 1, "{\"a\":Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":.Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":_Infinity}"},
|
||||||
|
{__LINE__, 0, "{\"a\":_nfinity}"},
|
||||||
|
{__LINE__, 1, "{\"a\":-Infinity}"}
|
||||||
|
};
|
||||||
|
for (size_t tdi = 0; tdi < sizeof(test_data) / sizeof(*test_data); ++tdi) {
|
||||||
|
const TestData& td = test_data[tdi];
|
||||||
|
bool ok = reader->parse(&*td.in.begin(),
|
||||||
|
&*td.in.begin() + td.in.size(),
|
||||||
|
&root, &errs);
|
||||||
|
JSONTEST_ASSERT(td.ok == ok)
|
||||||
|
<< "line:" << td.line << "\n"
|
||||||
|
<< " expected: {"
|
||||||
|
<< "ok:" << td.ok
|
||||||
|
<< ", in:\'" << td.in << "\'"
|
||||||
|
<< "}\n"
|
||||||
|
<< " actual: {"
|
||||||
|
<< "ok:" << ok
|
||||||
|
<< "}\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
char const doc[] = "{\"posInf\": Infinity, \"NegInf\": -Infinity}";
|
||||||
|
bool ok = reader->parse(
|
||||||
|
doc, doc + std::strlen(doc),
|
||||||
|
&root, &errs);
|
||||||
|
JSONTEST_ASSERT(ok);
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("", errs);
|
||||||
|
JSONTEST_ASSERT_EQUAL(2u, root.size());
|
||||||
|
JSONTEST_ASSERT_EQUAL(std::numeric_limits<double>::infinity(), root["posInf"].asDouble());
|
||||||
|
JSONTEST_ASSERT_EQUAL(-std::numeric_limits<double>::infinity(), root["NegInf"].asDouble());
|
||||||
|
}
|
||||||
|
delete reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct BuilderTest : JsonTest::TestCase {};
|
struct BuilderTest : JsonTest::TestCase {};
|
||||||
@@ -2274,7 +2425,7 @@ JSONTEST_FIXTURE(IteratorTest, distance) {
|
|||||||
json["k1"] = "a";
|
json["k1"] = "a";
|
||||||
json["k2"] = "b";
|
json["k2"] = "b";
|
||||||
int dist = 0;
|
int dist = 0;
|
||||||
std::string str;
|
JSONCPP_STRING str;
|
||||||
for (Json::ValueIterator it = json.begin(); it != json.end(); ++it) {
|
for (Json::ValueIterator it = json.begin(); it != json.end(); ++it) {
|
||||||
dist = it - json.begin();
|
dist = it - json.begin();
|
||||||
str = it->asString().c_str();
|
str = it->asString().c_str();
|
||||||
@@ -2283,12 +2434,89 @@ JSONTEST_FIXTURE(IteratorTest, distance) {
|
|||||||
JSONTEST_ASSERT_STRING_EQUAL("b", str);
|
JSONTEST_ASSERT_STRING_EQUAL("b", str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(IteratorTest, names) {
|
||||||
|
Json::Value json;
|
||||||
|
json["k1"] = "a";
|
||||||
|
json["k2"] = "b";
|
||||||
|
Json::ValueIterator it = json.begin();
|
||||||
|
JSONTEST_ASSERT(it != json.end());
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Value("k1"), it.key());
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("k1", it.name());
|
||||||
|
JSONTEST_ASSERT_EQUAL(-1, it.index());
|
||||||
|
++it;
|
||||||
|
JSONTEST_ASSERT(it != json.end());
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Value("k2"), it.key());
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("k2", it.name());
|
||||||
|
JSONTEST_ASSERT_EQUAL(-1, it.index());
|
||||||
|
++it;
|
||||||
|
JSONTEST_ASSERT(it == json.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(IteratorTest, indexes) {
|
||||||
|
Json::Value json;
|
||||||
|
json[0] = "a";
|
||||||
|
json[1] = "b";
|
||||||
|
Json::ValueIterator it = json.begin();
|
||||||
|
JSONTEST_ASSERT(it != json.end());
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(0)), it.key());
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("", it.name());
|
||||||
|
JSONTEST_ASSERT_EQUAL(0, it.index());
|
||||||
|
++it;
|
||||||
|
JSONTEST_ASSERT(it != json.end());
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::Value(Json::ArrayIndex(1)), it.key());
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL("", it.name());
|
||||||
|
JSONTEST_ASSERT_EQUAL(1, it.index());
|
||||||
|
++it;
|
||||||
|
JSONTEST_ASSERT(it == json.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(IteratorTest, const) {
|
||||||
|
Json::Value const v;
|
||||||
|
JSONTEST_ASSERT_THROWS(
|
||||||
|
Json::Value::iterator it(v.begin()) // Compile, but throw.
|
||||||
|
);
|
||||||
|
|
||||||
|
Json::Value value;
|
||||||
|
|
||||||
|
for(int i = 9; i < 12; ++i)
|
||||||
|
{
|
||||||
|
JSONCPP_OSTRINGSTREAM out;
|
||||||
|
out << std::setw(2) << i;
|
||||||
|
JSONCPP_STRING str = out.str();
|
||||||
|
value[str] = str;
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONCPP_OSTRINGSTREAM out;
|
||||||
|
//in old code, this will get a compile error
|
||||||
|
Json::Value::const_iterator iter = value.begin();
|
||||||
|
for(; iter != value.end(); ++iter)
|
||||||
|
{
|
||||||
|
out << *iter << ',';
|
||||||
|
}
|
||||||
|
JSONCPP_STRING expected = "\" 9\",\"10\",\"11\",";
|
||||||
|
JSONTEST_ASSERT_STRING_EQUAL(expected, out.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RValueTest : JsonTest::TestCase {};
|
||||||
|
|
||||||
|
JSONTEST_FIXTURE(RValueTest, moveConstruction) {
|
||||||
|
#if JSON_HAS_RVALUE_REFERENCES
|
||||||
|
Json::Value json;
|
||||||
|
json["key"] = "value";
|
||||||
|
Json::Value moved = std::move(json);
|
||||||
|
JSONTEST_ASSERT(moved != json); // Possibly not nullValue; definitely not equal.
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::objectValue, moved.type());
|
||||||
|
JSONTEST_ASSERT_EQUAL(Json::stringValue, moved["key"].type());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
JsonTest::Runner runner;
|
JsonTest::Runner runner;
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, checkNormalizeFloatingPointStr);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, memberCount);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, objects);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrays);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, arrayIssue252);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, null);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, strings);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, bools);
|
||||||
@@ -2310,6 +2538,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
//JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nulls);
|
//JSONTEST_REGISTER_FIXTURE(runner, ValueTest, nulls);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroes);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, zeroesInKeys);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, specialFloats);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, ValueTest, precision);
|
||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
|
JSONTEST_REGISTER_FIXTURE(runner, WriterTest, dropNullPlaceholders);
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
|
JSONTEST_REGISTER_FIXTURE(runner, StreamWriterTest, dropNullPlaceholders);
|
||||||
@@ -2344,9 +2574,16 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowZeroesTest, issue176);
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowZeroesTest, issue176);
|
||||||
|
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, CharReaderAllowSpecialFloatsTest, issue209);
|
||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, BuilderTest, settings);
|
JSONTEST_REGISTER_FIXTURE(runner, BuilderTest, settings);
|
||||||
|
|
||||||
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
|
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, distance);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, names);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, indexes);
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, IteratorTest, const);
|
||||||
|
|
||||||
|
JSONTEST_REGISTER_FIXTURE(runner, RValueTest, moveConstruction);
|
||||||
|
|
||||||
return runner.runCommandLine(argc, argv);
|
return runner.runCommandLine(argc, argv);
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,10 @@
|
|||||||
# removes all files created during testing
|
# Copyright 2007 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
|
||||||
|
|
||||||
|
"""Removes all files created during testing."""
|
||||||
|
|
||||||
import glob
|
import glob
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
1
test/data/fail_test_stack_limit.json
Normal file
1
test/data/fail_test_stack_limit.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 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
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import glob
|
import glob
|
||||||
import os.path
|
import os.path
|
||||||
|
@@ -1,4 +1,11 @@
|
|||||||
# Simple implementation of a json test runner to run the test against json-py.
|
# Copyright 2007 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
|
||||||
|
|
||||||
|
"""Simple implementation of a json test runner to run the test against
|
||||||
|
json-py."""
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import sys
|
import sys
|
||||||
import os.path
|
import os.path
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2007 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
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from io import open
|
from io import open
|
||||||
|
@@ -1,3 +1,8 @@
|
|||||||
|
# Copyright 2009 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
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from io import open
|
from io import open
|
||||||
|
23
travis.sh
Executable file
23
travis.sh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# 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:
|
||||||
|
# - SHARED_LIB=ON/OFF
|
||||||
|
# - STATIC_LIB=ON/OFF
|
||||||
|
# - CMAKE_PKG=ON/OFF
|
||||||
|
# - BUILD_TYPE=release/debug
|
||||||
|
# - VERBOSE_MAKE=false/true
|
||||||
|
# - VERBOSE (set or not)
|
||||||
|
|
||||||
|
# -e: fail on error
|
||||||
|
# -v: show commands
|
||||||
|
# -x: show expanded commands
|
||||||
|
set -vex
|
||||||
|
|
||||||
|
env | sort
|
||||||
|
|
||||||
|
meson --buildtype ${BUILD_TYPE} --default-library ${LIB_TYPE} . build-${LIB_TYPE}
|
||||||
|
ninja -v -C build-${LIB_TYPE}
|
||||||
|
ninja -v -C build-${LIB_TYPE} test
|
||||||
|
rm -r build-${LIB_TYPE}
|
Reference in New Issue
Block a user