Compare commits

..

64 Commits
1.9.2 ... 1.9.4

Author SHA1 Message Date
Jordan Bayles
9059f5cad0 Roll version numbers for 1.9.4 release (#1223) 2020-09-25 19:19:16 -07:00
Daniel Engberg
45733df96c meson: Don't specifically look for python3
Not all distributions provide Python as python3 and as Meson already depends on 3.5+ just use what Meson uses.
References: https://mesonbuild.com/Getting-meson.html
https://mesonbuild.com/Python-module.html#find_installation

Signed-off-by: Daniel Engberg <daniel.engberg.lists@pyret.net>
2020-09-01 23:02:57 -05:00
Ben Wolsieffer
5be07bdc5e Fix generation of pkg-config file with absolute includedir/libdir. (#1199) 2020-07-20 20:36:30 +08:00
Chen
bf0cfa5b46 hot fix for building static lib (#1203)
Fix #1197
2020-07-14 16:37:22 +08:00
Chen
cfc1ad72ad Enhance cmake script (#1197)
* BUILD_TYPE corresponds to Release/Debug
   but LIB_TYPE corresponds to shared/static.

* Add support to build shared, static and object lib at the same time.
2020-07-13 20:33:58 +08:00
nathanruiz
c8453d39d1 Delete nullptr Json::Value constructor (#1194)
This patch adds an explicit ctor with a std::nullptr_t argument, that is `delete`-d. This keeps Json::Value from exposing a coding error when automatically promoted to a const char* type.
2020-06-23 14:52:28 -07:00
Billy Donahue
632044ad95 Billy donahue avoid isprint (#1191)
* avoid isprint

`std::isprint` is locale-specific and the JSON-spec is not.
In particular, isprint('\t') is true in Windows CP1252.

Has bitten others, e.g. https://github.com/laurikari/tre/issues/64

Fixes #1187

* semicolon (rookie mistake!)

* Windows tab escape testing with custom locale (#1190)

Co-authored-by: Nikolay Baklicharov <thestorm.nik@gmail.com>
2020-06-11 18:14:03 -04:00
Billy Donahue
b3189a0800 avoid isprint, because it is locale specific (#1189)
* avoid isprint

`std::isprint` is locale-specific and the JSON-spec is not.
In particular, isprint('\t') is true in Windows CP1252.

Has bitten others, e.g. https://github.com/laurikari/tre/issues/64

Fixes #1187

* semicolon (rookie mistake!)
2020-06-11 17:43:44 -04:00
Jordan Bayles
9be5895985 Issue 1182: Fix fuzzing bug (#1183)
This patch fixes a fuzzing bug by resolving a bad fallthrough in the
setComment logic.

The result is that we get a proper error instead of an assert, making
the library friendlier to use and less likely to cause issue for
consumers.

See related Chromium project bug:
https://bugs.chromium.org/p/chromium/issues/detail?id=989851

Issue: 1182
2020-05-30 20:20:20 -07:00
kabeer27
6aba23f4a8 Fixes Oss-Fuzz issue: 21916 (#1180)
* Fix heap-buffer-overflow in json_reader
2020-05-29 21:50:26 +08:00
Billy Donahue
c161f4ac69 Escape control chars even if emitting UTF8 (#1178)
* Escape control chars even if emitting UTF8

See #1176
Fixes #1175

* review comments

* fix test by stopping early enough to punt on utf8-input.
2020-05-21 11:30:59 -04:00
Billy Donahue
75b360af4a spot fix #1171: isprint argument must be representable as unsigned char (#1173) 2020-05-13 18:37:02 -04:00
Rosen Penev
e36cff19f0 clang-tidy + any_of usage (#1171)
* [clang-tidy] change functions to static

Found with readability-convert-member-functions-to-static

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

* optimize JsonWriter::validate #1171

* do the same for json_reader

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

* use std::any_of

Also simplified two loops.

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

Co-authored-by: Billy Donahue <billy.donahue@gmail.com>
2020-05-12 19:19:36 -04:00
Edward Brey
b8cb8889aa Added current dir specifier for PowerShell (#1169)
The `./` is needed before `vcpkg install jsoncpp` when installing with PowerShell.
2020-05-08 09:00:12 +08:00
Chen
d2d4c74a03 Update README.md and add dota17 to AUTHORS list. (#1168)
* update README

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

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

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

Found with readability-redundant-string-init

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

* [clang-tidy] switch to raw strings

Easier to read.

Found with modernize-raw-string-literal

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

* [clang-tidy] fix performance issues

Found with performance*

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

* fix extra comma warnings

Found with clang's -Wextra-semi-stmt

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

* remove JSONCPP_OP_EXPLICIT

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

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

* remove JSONCPP_NOEXCEPT

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

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

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

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

Use 4 spaces for indent, no tabs

* Use ccache right

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

Found with readability-else-after-return

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

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

Found with modernize-loop-convert

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

* [clang-tidy] Replace deprecated C headers

Found with modernize-deprecated-headers

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

* [clang-tidy] Use auto where applicable

Found with modernize-use-auto

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

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

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

* Bump version to 1.9.3

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

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

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

This shows up as a test failure:

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

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

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

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

change an int to size_t #1113

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

* add a helper function

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

* remove C ++ compiler version switch for smart pointer

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

View File

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

1
.gitignore vendored
View File

@@ -28,7 +28,6 @@
# CMake-generated files: # CMake-generated files:
CMakeFiles/ CMakeFiles/
*.cmake
/pkg-config/jsoncpp.pc /pkg-config/jsoncpp.pc
jsoncpp_lib_static.dir/ jsoncpp_lib_static.dir/

View File

@@ -66,7 +66,7 @@ cmake --version
echo ${CXX} echo ${CXX}
${CXX} --version ${CXX} --version
_COMPILER_NAME=`basename ${CXX}` _COMPILER_NAME=`basename ${CXX}`
if [ "${BUILD_TYPE}" == "shared" ]; then if [ "${LIB_TYPE}" = "shared" ]; then
_CMAKE_BUILD_SHARED_LIBS=ON _CMAKE_BUILD_SHARED_LIBS=ON
else else
_CMAKE_BUILD_SHARED_LIBS=OFF _CMAKE_BUILD_SHARED_LIBS=OFF

View File

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

View File

@@ -37,44 +37,43 @@ foreach(pold "") # Currently Empty
endif() endif()
endforeach() endforeach()
# ==== Define language standard configurations requiring at least c++11 standard # Build the library with C++11 standard support, independent from other including
if(CMAKE_CXX_STANDARD EQUAL "98" ) # software which may use a different CXX_STANDARD or CMAKE_CXX_STANDARD.
message(FATAL_ERROR "CMAKE_CXX_STANDARD:STRING=98 is not supported.") set(CMAKE_CXX_STANDARD 11)
endif() set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
##### # Ensure that CMAKE_BUILD_TYPE has a value specified for single configuration generators.
## Set the default target properties if(NOT DEFINED CMAKE_BUILD_TYPE AND NOT DEFINED CMAKE_CONFIGURATION_TYPES)
if(NOT CMAKE_CXX_STANDARD)
set(CMAKE_CXX_STANDARD 11) # Supported values are ``11``, ``14``, and ``17``.
endif()
if(NOT CMAKE_CXX_STANDARD_REQUIRED)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif()
if(NOT CMAKE_CXX_EXTENSIONS)
set(CMAKE_CXX_EXTENSIONS OFF)
endif()
# ====
# Ensures that CMAKE_BUILD_TYPE has a default value
if(NOT DEFINED CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Release CACHE STRING set(CMAKE_BUILD_TYPE Release CACHE STRING
"Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.") "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Coverage.")
endif() endif()
project(JSONCPP set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
# ---------------------------------------------------------------------------
# use ccache if found, has to be done before project()
# ---------------------------------------------------------------------------
find_program(CCACHE_EXECUTABLE "ccache" HINTS /usr/local/bin /opt/local/bin)
if(CCACHE_EXECUTABLE)
message(STATUS "use ccache")
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_EXECUTABLE}" CACHE PATH "ccache" FORCE)
endif()
project(jsoncpp
# Note: version must be updated in three places when doing a release. This # Note: version must be updated in three places when doing a release. This
# annoying process ensures that amalgamate, CMake, and meson all report the # annoying process ensures that amalgamate, CMake, and meson all report the
# correct version. # correct version.
# 1. /meson.build # 1. ./meson.build
# 2. /include/json/version.h # 2. ./include/json/version.h
# 3. /CMakeLists.txt # 3. ./CMakeLists.txt
# IMPORTANT: also update the SOVERSION!! # IMPORTANT: also update the PROJECT_SOVERSION!!
VERSION 1.9.2 # <major>[.<minor>[.<patch>[.<tweak>]]] VERSION 1.9.4 # <major>[.<minor>[.<patch>[.<tweak>]]]
LANGUAGES CXX) LANGUAGES CXX)
message(STATUS "JsonCpp Version: ${JSONCPP_VERSION_MAJOR}.${JSONCPP_VERSION_MINOR}.${JSONCPP_VERSION_PATCH}") message(STATUS "JsonCpp Version: ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set( JSONCPP_SOVERSION 22 ) set(PROJECT_SOVERSION 24)
option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON) option(JSONCPP_WITH_TESTS "Compile and (for jsoncpp_check) run JsonCpp test executables" ON)
option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON) option(JSONCPP_WITH_POST_BUILD_UNITTEST "Automatically run unit-tests as a post build step" ON)
@@ -82,120 +81,80 @@ option(JSONCPP_WITH_WARNING_AS_ERROR "Force compilation to fail if a warning occ
option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON) option(JSONCPP_WITH_STRICT_ISO "Issue all the warnings demanded by strict ISO C and ISO C++" ON)
option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON) option(JSONCPP_WITH_PKGCONFIG_SUPPORT "Generate and install .pc files" ON)
option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON) option(JSONCPP_WITH_CMAKE_PACKAGE "Generate and install cmake package files" ON)
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." OFF) option(JSONCPP_WITH_EXAMPLE "Compile JsonCpp example" OFF)
option(BUILD_SHARED_LIBS "Build jsoncpp_lib as a shared library." ON)
# Enable runtime search path support for dynamic libraries on OSX option(BUILD_STATIC_LIBS "Build jsoncpp_lib as a static library." ON)
if(APPLE) option(BUILD_OBJECT_LIBS "Build jsoncpp_lib as a object library." ON)
set(CMAKE_MACOSX_RPATH 1)
endif()
# Adhere to GNU filesystem layout conventions # Adhere to GNU filesystem layout conventions
include(GNUInstallDirs) include(GNUInstallDirs)
set(DEBUG_LIBNAME_SUFFIX "" CACHE STRING "Optional suffix to append to the library name for a debug build") set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Archive output dir.")
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib" CACHE PATH "Library output dir.")
set(CMAKE_PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "PDB (MSVC debug symbol)output dir.")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin" CACHE PATH "Executable/dll output dir.")
set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL" ) set(JSONCPP_USE_SECURE_MEMORY "0" CACHE STRING "-D...=1 to use memory-wiping allocator for STL")
configure_file( "${PROJECT_SOURCE_DIR}/version.in" configure_file("${PROJECT_SOURCE_DIR}/version.in"
"${PROJECT_BINARY_DIR}/version" "${PROJECT_BINARY_DIR}/version"
NEWLINE_STYLE UNIX ) NEWLINE_STYLE UNIX)
macro(UseCompilationWarningAsError) macro(use_compilation_warning_as_error)
if(MSVC) if(MSVC)
# Only enabled in debug because some old versions of VS STL generate # Only enabled in debug because some old versions of VS STL generate
# warnings when compiled in release configuration. # warnings when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/WX>) add_compile_options($<$<CONFIG:Debug>:/WX>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /WX ")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror) add_compile_options(-Werror)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
endif()
if(JSONCPP_WITH_STRICT_ISO) if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-pedantic-errors) add_compile_options(-pedantic-errors)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
endif()
endif() endif()
endif() endif()
endmacro() endmacro()
# Include our configuration header # Include our configuration header
include_directories( ${jsoncpp_SOURCE_DIR}/include ) include_directories(${jsoncpp_SOURCE_DIR}/include)
if(MSVC) if(MSVC)
# Only enabled in debug because some old versions of VS STL generate # Only enabled in debug because some old versions of VS STL generate
# unreachable code warning when compiled in release configuration. # unreachable code warning when compiled in release configuration.
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options($<$<CONFIG:Debug>:/W4>) add_compile_options($<$<CONFIG:Debug>:/W4>)
else()
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /W4 ")
endif()
endif() endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
# using regular Clang or AppleClang # using regular Clang or AppleClang
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare) add_compile_options(-Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Werror=conversion -Werror=sign-compare")
endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# using GCC # using GCC
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra) add_compile_options(-Wall -Wconversion -Wshadow -Wextra)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra")
endif()
# not yet ready for -Wsign-conversion # not yet ready for -Wsign-conversion
if(JSONCPP_WITH_STRICT_ISO) if(JSONCPP_WITH_STRICT_ISO)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0) add_compile_options(-Wpedantic)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
endif() endif()
if(JSONCPP_WITH_WARNING_AS_ERROR) if(JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Werror=conversion) add_compile_options(-Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=conversion")
endif()
endif() endif()
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel") elseif(CMAKE_CXX_COMPILER_ID STREQUAL "Intel")
# using Intel compiler # using Intel compiler
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion) add_compile_options(-Wall -Wconversion -Wshadow -Wextra -Werror=conversion)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wconversion -Wshadow -Wextra -Werror=conversion")
endif()
if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR) if(JSONCPP_WITH_STRICT_ISO AND NOT JSONCPP_WITH_WARNING_AS_ERROR)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0) add_compile_options(-Wpedantic)
add_compile_options(-pedantic)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic")
endif()
endif() endif()
endif() endif()
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ccache)
endif(CCACHE_FOUND)
if(JSONCPP_WITH_WARNING_AS_ERROR) if(JSONCPP_WITH_WARNING_AS_ERROR)
UseCompilationWarningAsError() use_compilation_warning_as_error()
endif() endif()
if(JSONCPP_WITH_PKGCONFIG_SUPPORT) if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
include(JoinPaths)
join_paths(libdir_for_pc_file "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}")
join_paths(includedir_for_pc_file "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}")
configure_file( configure_file(
"pkg-config/jsoncpp.pc.in" "pkg-config/jsoncpp.pc.in"
"pkg-config/jsoncpp.pc" "pkg-config/jsoncpp.pc"
@@ -205,11 +164,11 @@ if(JSONCPP_WITH_PKGCONFIG_SUPPORT)
endif() endif()
if(JSONCPP_WITH_CMAKE_PACKAGE) if(JSONCPP_WITH_CMAKE_PACKAGE)
include (CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
install(EXPORT jsoncpp install(EXPORT jsoncpp
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/jsoncpp
FILE jsoncppConfig.cmake) FILE jsoncppConfig.cmake)
write_basic_package_version_file ("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake" write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake"
VERSION ${PROJECT_VERSION} VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion) COMPATIBILITY SameMajorVersion)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jsoncppConfigVersion.cmake
@@ -222,10 +181,12 @@ if(JSONCPP_WITH_TESTS)
endif() endif()
# Build the different applications # Build the different applications
add_subdirectory( src ) add_subdirectory(src)
#install the includes #install the includes
add_subdirectory( include ) add_subdirectory(include)
#install the example #install the example
add_subdirectory( example ) if(JSONCPP_WITH_EXAMPLE)
add_subdirectory(example)
endif()

View File

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

View File

@@ -30,8 +30,14 @@ format to store user input files.
* `1.y.z` is built with C++11. * `1.y.z` is built with C++11.
* `0.y.z` can be used with older compilers. * `0.y.z` can be used with older compilers.
* `00.11.z` can be used both in old and new compilers.
* Major versions maintain binary-compatibility. * Major versions maintain binary-compatibility.
### Special note
The branch `00.11.z`is a new branch, its major version number `00` is to show that it is
different from `0.y.z` and `1.y.z`, the main purpose of this branch is to make a balance
between the other two branches. Thus, users can use some new features in this new branch
that introduced in 1.y.z, but can hardly applied into 0.y.z.
## Using JsonCpp in your project ## Using JsonCpp in your project
@@ -42,7 +48,7 @@ You can download and install JsonCpp using the [vcpkg](https://github.com/Micros
cd vcpkg cd vcpkg
./bootstrap-vcpkg.sh ./bootstrap-vcpkg.sh
./vcpkg integrate install ./vcpkg integrate install
vcpkg install jsoncpp ./vcpkg install jsoncpp
The JsonCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. The JsonCpp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.

View File

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

23
cmake/JoinPaths.cmake Normal file
View File

@@ -0,0 +1,23 @@
# This module provides a function for joining paths
# known from most languages
#
# SPDX-License-Identifier: (MIT OR CC0-1.0)
# Copyright 2020 Jan Tojnar
# https://github.com/jtojnar/cmake-snips
#
# Modelled after Pythons os.path.join
# https://docs.python.org/3.7/library/os.path.html#os.path.join
# Windows not supported
function(join_paths joined_path first_path_segment)
set(temp_path "${first_path_segment}")
foreach(current_segment IN LISTS ARGN)
if(NOT ("${current_segment}" STREQUAL ""))
if(IS_ABSOLUTE "${current_segment}")
set(temp_path "${current_segment}")
else()
set(temp_path "${temp_path}/${current_segment}")
endif()
endif()
endforeach()
set(${joined_path} "${temp_path}" PARENT_SCOPE)
endfunction()

View File

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

View File

@@ -11,7 +11,7 @@
*/ */
int main() { int main() {
const std::string rawJson = R"({"Age": 20, "Name": "colin"})"; const std::string rawJson = R"({"Age": 20, "Name": "colin"})";
const int rawJsonLength = static_cast<int>(rawJson.length()); const auto rawJsonLength = static_cast<int>(rawJson.length());
constexpr bool shouldUseOldWay = false; constexpr bool shouldUseOldWay = false;
JSONCPP_STRING err; JSONCPP_STRING err;
Json::Value root; Json::Value root;

View File

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

View File

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

View File

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

View File

@@ -14,16 +14,6 @@
#include <string> #include <string>
#include <type_traits> #include <type_traits>
/// If defined, indicates that json library is embedded in CppTL library.
//# define JSON_IN_CPPTL 1
/// If defined, indicates that json may leverage CppTL library
//# define JSON_USE_CPPTL 1
/// If defined, indicates that cpptl vector based map should be used instead of
/// std::map
/// as Value container.
//# define JSON_USE_CPPTL_SMALLMAP 1
// If non-zero, the library uses exceptions to report bad input instead of C // If non-zero, the library uses exceptions to report bad input instead of C
// assertion macros. The default is to use exceptions. // assertion macros. The default is to use exceptions.
#ifndef JSON_USE_EXCEPTION #ifndef JSON_USE_EXCEPTION
@@ -40,28 +30,22 @@
/// Remarks: it is automatically defined in the generated amalgamated header. /// Remarks: it is automatically defined in the generated amalgamated header.
// #define JSON_IS_AMALGAMATION // #define JSON_IS_AMALGAMATION
#ifdef JSON_IN_CPPTL // Export macros for DLL visibility
#include <cpptl/config.h> #if defined(JSON_DLL_BUILD)
#ifndef JSON_USE_CPPTL
#define JSON_USE_CPPTL 1
#endif
#endif
#ifdef JSON_IN_CPPTL
#define JSON_API CPPTL_API
#elif defined(JSON_DLL_BUILD)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllexport) #define JSON_API __declspec(dllexport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#elif defined(__GNUC__) || defined(__clang__) #elif defined(__GNUC__) || defined(__clang__)
#define JSON_API __attribute__((visibility("default"))) #define JSON_API __attribute__((visibility("default")))
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#elif defined(JSON_DLL) #elif defined(JSON_DLL)
#if defined(_MSC_VER) || defined(__MINGW32__) #if defined(_MSC_VER) || defined(__MINGW32__)
#define JSON_API __declspec(dllimport) #define JSON_API __declspec(dllimport)
#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING #define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
#endif // ifdef JSON_IN_CPPTL #endif // ifdef JSON_DLL_BUILD
#if !defined(JSON_API) #if !defined(JSON_API)
#define JSON_API #define JSON_API
#endif #endif
@@ -90,20 +74,6 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
// C++11 should be used directly in JSONCPP. // C++11 should be used directly in JSONCPP.
#define JSONCPP_OVERRIDE override #define JSONCPP_OVERRIDE override
#if __cplusplus >= 201103L
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER < 1900
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT explicit
#elif defined(_MSC_VER) && _MSC_VER >= 1900
#define JSONCPP_NOEXCEPT noexcept
#define JSONCPP_OP_EXPLICIT explicit
#else
#define JSONCPP_NOEXCEPT throw()
#define JSONCPP_OP_EXPLICIT
#endif
#ifdef __clang__ #ifdef __clang__
#if __has_extension(attribute_deprecated_with_message) #if __has_extension(attribute_deprecated_with_message)
#define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message))) #define JSONCPP_DEPRECATED(message) __attribute__((deprecated(message)))
@@ -135,23 +105,23 @@ extern JSON_API int msvc_pre1900_c99_snprintf(char* outBuf, size_t size,
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
namespace Json { namespace Json {
typedef int Int; using Int = int;
typedef unsigned int UInt; using UInt = unsigned int;
#if defined(JSON_NO_INT64) #if defined(JSON_NO_INT64)
typedef int LargestInt; using LargestInt = int;
typedef unsigned int LargestUInt; using LargestUInt = unsigned int;
#undef JSON_HAS_INT64 #undef JSON_HAS_INT64
#else // if defined(JSON_NO_INT64) #else // if defined(JSON_NO_INT64)
// For Microsoft Visual use specific types as long long is not supported // For Microsoft Visual use specific types as long long is not supported
#if defined(_MSC_VER) // Microsoft Visual Studio #if defined(_MSC_VER) // Microsoft Visual Studio
typedef __int64 Int64; using Int64 = __int64;
typedef unsigned __int64 UInt64; using UInt64 = unsigned __int64;
#else // if defined(_MSC_VER) // Other platforms, use long long #else // if defined(_MSC_VER) // Other platforms, use long long
typedef int64_t Int64; using Int64 = int64_t;
typedef uint64_t UInt64; using UInt64 = uint64_t;
#endif // if defined(_MSC_VER) #endif // if defined(_MSC_VER)
typedef Int64 LargestInt; using LargestInt = Int64;
typedef UInt64 LargestUInt; using LargestUInt = UInt64;
#define JSON_HAS_INT64 #define JSON_HAS_INT64
#endif // if defined(JSON_NO_INT64) #endif // if defined(JSON_NO_INT64)

View File

@@ -29,7 +29,7 @@ class CharReaderBuilder;
class Features; class Features;
// value.h // value.h
typedef unsigned int ArrayIndex; using ArrayIndex = unsigned int;
class StaticString; class StaticString;
class Path; class Path;
class PathArgument; class PathArgument;

View File

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

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction. // recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_FEATURES_H_INCLUDED #ifndef JSON_FEATURES_H_INCLUDED
#define CPPTL_JSON_FEATURES_H_INCLUDED #define JSON_FEATURES_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION) #if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h" #include "forwards.h"
@@ -58,4 +58,4 @@ public:
#pragma pack(pop) #pragma pack(pop)
#endif // CPPTL_JSON_FEATURES_H_INCLUDED #endif // JSON_FEATURES_H_INCLUDED

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction. // recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_READER_H_INCLUDED #ifndef JSON_READER_H_INCLUDED
#define CPPTL_JSON_READER_H_INCLUDED #define JSON_READER_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION) #if !defined(JSON_IS_AMALGAMATION)
#include "json_features.h" #include "json_features.h"
@@ -36,8 +36,8 @@ namespace Json {
class JSONCPP_DEPRECATED( class JSONCPP_DEPRECATED(
"Use CharReader and CharReaderBuilder instead.") JSON_API Reader { "Use CharReader and CharReaderBuilder instead.") JSON_API Reader {
public: public:
typedef char Char; using Char = char;
typedef const Char* Location; using Location = const Char*;
/** \brief An error tagged with where in the JSON text it was encountered. /** \brief An error tagged with where in the JSON text it was encountered.
* *
@@ -187,7 +187,7 @@ private:
Location extra_; Location extra_;
}; };
typedef std::deque<ErrorInfo> Errors; using Errors = std::deque<ErrorInfo>;
bool readToken(Token& token); bool readToken(Token& token);
void skipSpaces(); void skipSpaces();
@@ -226,7 +226,7 @@ private:
static bool containsNewLine(Location begin, Location end); static bool containsNewLine(Location begin, Location end);
static String normalizeEOL(Location begin, Location end); static String normalizeEOL(Location begin, Location end);
typedef std::stack<Value*> Nodes; using Nodes = std::stack<Value*>;
Nodes nodes_; Nodes nodes_;
Errors errors_; Errors errors_;
String document_; String document_;
@@ -299,6 +299,8 @@ public:
* if allowComments is false. * if allowComments is false.
* - `"allowComments": false or true` * - `"allowComments": false or true`
* - true if comments are allowed. * - true if comments are allowed.
* - `"allowTrailingCommas": false or true`
* - true if trailing commas in objects and arrays are allowed.
* - `"strictRoot": false or true` * - `"strictRoot": false or true`
* - true if root must be either an array or an object value * - true if root must be either an array or an object value
* - `"allowDroppedNullPlaceholders": false or true` * - `"allowDroppedNullPlaceholders": false or true`
@@ -398,4 +400,4 @@ JSON_API IStream& operator>>(IStream&, Value&);
#pragma warning(pop) #pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_READER_H_INCLUDED #endif // JSON_READER_H_INCLUDED

View File

@@ -3,8 +3,8 @@
// recognized in your jurisdiction. // recognized in your jurisdiction.
// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE // See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
#ifndef CPPTL_JSON_H_INCLUDED #ifndef JSON_H_INCLUDED
#define CPPTL_JSON_H_INCLUDED #define JSON_H_INCLUDED
#if !defined(JSON_IS_AMALGAMATION) #if !defined(JSON_IS_AMALGAMATION)
#include "forwards.h" #include "forwards.h"
@@ -21,21 +21,31 @@
#endif #endif
#endif #endif
// Support for '= delete' with template declarations was a late addition
// to the c++11 standard and is rejected by clang 3.8 and Apple clang 8.2
// even though these declare themselves to be c++11 compilers.
#if !defined(JSONCPP_TEMPLATE_DELETE)
#if defined(__clang__) && defined(__apple_build_version__)
#if __apple_build_version__ <= 8000042
#define JSONCPP_TEMPLATE_DELETE
#endif
#elif defined(__clang__)
#if __clang_major__ == 3 && __clang_minor__ <= 8
#define JSONCPP_TEMPLATE_DELETE
#endif
#endif
#if !defined(JSONCPP_TEMPLATE_DELETE)
#define JSONCPP_TEMPLATE_DELETE = delete
#endif
#endif
#include <array> #include <array>
#include <exception> #include <exception>
#include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#ifndef JSON_USE_CPPTL_SMALLMAP
#include <map>
#else
#include <cpptl/smallmap.h>
#endif
#ifdef JSON_USE_CPPTL
#include <cpptl/forwards.h>
#endif
// Disable warning C4251: <data member>: <type> needs to have dll-interface to // Disable warning C4251: <data member>: <type> needs to have dll-interface to
// be used by... // be used by...
#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
@@ -57,8 +67,8 @@ namespace Json {
class JSON_API Exception : public std::exception { class JSON_API Exception : public std::exception {
public: public:
Exception(String msg); Exception(String msg);
~Exception() JSONCPP_NOEXCEPT override; ~Exception() noexcept override;
char const* what() const JSONCPP_NOEXCEPT override; char const* what() const noexcept override;
protected: protected:
String msg_; String msg_;
@@ -120,11 +130,6 @@ enum PrecisionType {
decimalPlaces ///< we set max number of digits after "." in string decimalPlaces ///< we set max number of digits after "." in string
}; };
//# ifdef JSON_USE_CPPTL
// typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
// typedef CppTL::AnyEnumerator<const Value &> EnumValues;
//# endif
/** \brief Lightweight wrapper to tag static string. /** \brief Lightweight wrapper to tag static string.
* *
* Value constructor and objectValue member assignment takes advantage of the * Value constructor and objectValue member assignment takes advantage of the
@@ -189,21 +194,21 @@ class JSON_API Value {
friend class ValueIteratorBase; friend class ValueIteratorBase;
public: public:
typedef std::vector<String> Members; using Members = std::vector<String>;
typedef ValueIterator iterator; using iterator = ValueIterator;
typedef ValueConstIterator const_iterator; using const_iterator = ValueConstIterator;
typedef Json::UInt UInt; using UInt = Json::UInt;
typedef Json::Int Int; using Int = Json::Int;
#if defined(JSON_HAS_INT64) #if defined(JSON_HAS_INT64)
typedef Json::UInt64 UInt64; using UInt64 = Json::UInt64;
typedef Json::Int64 Int64; using Int64 = Json::Int64;
#endif // defined(JSON_HAS_INT64) #endif // defined(JSON_HAS_INT64)
typedef Json::LargestInt LargestInt; using LargestInt = Json::LargestInt;
typedef Json::LargestUInt LargestUInt; using LargestUInt = Json::LargestUInt;
typedef Json::ArrayIndex ArrayIndex; using ArrayIndex = Json::ArrayIndex;
// Required for boost integration, e. g. BOOST_TEST // Required for boost integration, e. g. BOOST_TEST
typedef std::string value_type; using value_type = std::string;
#if JSON_USE_NULLREF #if JSON_USE_NULLREF
// Binary compatibility kludges, do not use. // Binary compatibility kludges, do not use.
@@ -287,11 +292,7 @@ private:
}; };
public: public:
#ifndef JSON_USE_CPPTL_SMALLMAP
typedef std::map<CZString, Value> ObjectValues; typedef std::map<CZString, Value> ObjectValues;
#else
typedef CppTL::SmallMap<CZString, Value> ObjectValues;
#endif // ifndef JSON_USE_CPPTL_SMALLMAP
#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION #endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
public: public:
@@ -340,10 +341,8 @@ public:
*/ */
Value(const StaticString& value); Value(const StaticString& value);
Value(const String& value); Value(const String& value);
#ifdef JSON_USE_CPPTL
Value(const CppTL::ConstString& value);
#endif
Value(bool value); Value(bool value);
Value(std::nullptr_t ptr) = delete;
Value(const Value& other); Value(const Value& other);
Value(Value&& other); Value(Value&& other);
~Value(); ~Value();
@@ -384,9 +383,6 @@ public:
* \return false if !string. (Seg-fault if str or end are NULL.) * \return false if !string. (Seg-fault if str or end are NULL.)
*/ */
bool getString(char const** begin, char const** end) const; bool getString(char const** begin, char const** end) const;
#ifdef JSON_USE_CPPTL
CppTL::ConstString asConstString() const;
#endif
Int asInt() const; Int asInt() const;
UInt asUInt() const; UInt asUInt() const;
#if defined(JSON_HAS_INT64) #if defined(JSON_HAS_INT64)
@@ -413,8 +409,8 @@ public:
bool isObject() const; bool isObject() const;
/// The `as<T>` and `is<T>` member function templates and specializations. /// The `as<T>` and `is<T>` member function templates and specializations.
template <typename T> T as() const = delete; template <typename T> T as() const JSONCPP_TEMPLATE_DELETE;
template <typename T> bool is() const = delete; template <typename T> bool is() const JSONCPP_TEMPLATE_DELETE;
bool isConvertibleTo(ValueType other) const; bool isConvertibleTo(ValueType other) const;
@@ -426,7 +422,7 @@ public:
bool empty() const; bool empty() const;
/// Return !isNull() /// Return !isNull()
JSONCPP_OP_EXPLICIT operator bool() const; explicit operator bool() const;
/// Remove all object members and array elements. /// Remove all object members and array elements.
/// \pre type() is arrayValue, objectValue, or nullValue /// \pre type() is arrayValue, objectValue, or nullValue
@@ -468,8 +464,10 @@ public:
/// Equivalent to jsonvalue[jsonvalue.size()] = value; /// Equivalent to jsonvalue[jsonvalue.size()] = value;
Value& append(const Value& value); Value& append(const Value& value);
Value& append(Value&& value); Value& append(Value&& value);
/// \brief Insert value in array at specific index /// \brief Insert value in array at specific index
bool insert(ArrayIndex index, Value newValue); bool insert(ArrayIndex index, const Value& newValue);
bool insert(ArrayIndex index, Value&& newValue);
/// Access an object value by name, create a null member if it does not exist. /// Access an object value by name, create a null member if it does not exist.
/// \note Because of our implementation, keys are limited to 2^30 -1 chars. /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
@@ -498,13 +496,6 @@ public:
* \endcode * \endcode
*/ */
Value& operator[](const StaticString& key); Value& operator[](const StaticString& key);
#ifdef JSON_USE_CPPTL
/// Access an object value by name, create a null member if it does not exist.
Value& operator[](const CppTL::ConstString& key);
/// Access an object value by name, returns null if there is no member with
/// that name.
const Value& operator[](const CppTL::ConstString& key) const;
#endif
/// Return the member named key if it exist, defaultValue otherwise. /// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy /// \note deep copy
Value get(const char* key, const Value& defaultValue) const; Value get(const char* key, const Value& defaultValue) const;
@@ -517,11 +508,6 @@ public:
/// \note deep copy /// \note deep copy
/// \param key may contain embedded nulls. /// \param key may contain embedded nulls.
Value get(const String& key, const Value& defaultValue) const; Value get(const String& key, const Value& defaultValue) const;
#ifdef JSON_USE_CPPTL
/// Return the member named key if it exist, defaultValue otherwise.
/// \note deep copy
Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
#endif
/// Most general and efficient version of isMember()const, get()const, /// Most general and efficient version of isMember()const, get()const,
/// and operator[]const /// and operator[]const
/// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30 /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
@@ -567,10 +553,6 @@ public:
bool isMember(const String& key) const; bool isMember(const String& key) const;
/// Same as isMember(String const& key)const /// Same as isMember(String const& key)const
bool isMember(const char* begin, const char* end) const; bool isMember(const char* begin, const char* end) const;
#ifdef JSON_USE_CPPTL
/// Return true if the object has a member named key.
bool isMember(const CppTL::ConstString& key) const;
#endif
/// \brief Return a list of the member names. /// \brief Return a list of the member names.
/// ///
@@ -579,11 +561,6 @@ public:
/// \post if type() was nullValue, it remains nullValue /// \post if type() was nullValue, it remains nullValue
Members getMemberNames() const; Members getMemberNames() const;
//# ifdef JSON_USE_CPPTL
// EnumMemberNames enumMemberNames() const;
// EnumValues enumValues() const;
//# endif
/// \deprecated Always pass len. /// \deprecated Always pass len.
JSONCPP_DEPRECATED("Use setComment(String const&) instead.") JSONCPP_DEPRECATED("Use setComment(String const&) instead.")
void setComment(const char* comment, CommentPlacement placement) { void setComment(const char* comment, CommentPlacement placement) {
@@ -706,11 +683,6 @@ template <> inline float Value::as<float>() const { return asFloat(); }
template <> inline const char* Value::as<const char*>() const { template <> inline const char* Value::as<const char*>() const {
return asCString(); return asCString();
} }
#ifdef JSON_USE_CPPTL
template <> inline CppTL::ConstString Value::as<CppTL::ConstString>() const {
return asConstString();
}
#endif
/** \brief Experimental and untested: represents an element of the "path" to /** \brief Experimental and untested: represents an element of the "path" to
* access a node. * access a node.
@@ -757,8 +729,8 @@ public:
Value& make(Value& root) const; Value& make(Value& root) const;
private: private:
typedef std::vector<const PathArgument*> InArgs; using InArgs = std::vector<const PathArgument*>;
typedef std::vector<PathArgument> Args; using Args = std::vector<PathArgument>;
void makePath(const String& path, const InArgs& in); void makePath(const String& path, const InArgs& in);
void addPathInArg(const String& path, const InArgs& in, void addPathInArg(const String& path, const InArgs& in,
@@ -773,10 +745,10 @@ private:
*/ */
class JSON_API ValueIteratorBase { class JSON_API ValueIteratorBase {
public: public:
typedef std::bidirectional_iterator_tag iterator_category; using iterator_category = std::bidirectional_iterator_tag;
typedef unsigned int size_t; using size_t = unsigned int;
typedef int difference_type; using difference_type = int;
typedef ValueIteratorBase SelfType; using SelfType = ValueIteratorBase;
bool operator==(const SelfType& other) const { return isEqual(other); } bool operator==(const SelfType& other) const { return isEqual(other); }
@@ -849,12 +821,12 @@ class JSON_API ValueConstIterator : public ValueIteratorBase {
friend class Value; friend class Value;
public: public:
typedef const Value value_type; using value_type = const Value;
// typedef unsigned int size_t; // typedef unsigned int size_t;
// typedef int difference_type; // typedef int difference_type;
typedef const Value& reference; using reference = const Value&;
typedef const Value* pointer; using pointer = const Value*;
typedef ValueConstIterator SelfType; using SelfType = ValueConstIterator;
ValueConstIterator(); ValueConstIterator();
ValueConstIterator(ValueIterator const& other); ValueConstIterator(ValueIterator const& other);
@@ -900,12 +872,12 @@ class JSON_API ValueIterator : public ValueIteratorBase {
friend class Value; friend class Value;
public: public:
typedef Value value_type; using value_type = Value;
typedef unsigned int size_t; using size_t = unsigned int;
typedef int difference_type; using difference_type = int;
typedef Value& reference; using reference = Value&;
typedef Value* pointer; using pointer = Value*;
typedef ValueIterator SelfType; using SelfType = ValueIterator;
ValueIterator(); ValueIterator();
explicit ValueIterator(const ValueConstIterator& other); explicit ValueIterator(const ValueConstIterator& other);
@@ -960,4 +932,4 @@ inline void swap(Value& a, Value& b) { a.swap(b); }
#pragma warning(pop) #pragma warning(pop)
#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING) #endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
#endif // CPPTL_JSON_H_INCLUDED #endif // JSON_H_INCLUDED

View File

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

View File

@@ -252,7 +252,7 @@ private:
static bool hasCommentForValue(const Value& value); static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text); static String normalizeEOL(const String& text);
typedef std::vector<String> ChildValues; using ChildValues = std::vector<String>;
ChildValues childValues_; ChildValues childValues_;
String document_; String document_;
@@ -326,7 +326,7 @@ private:
static bool hasCommentForValue(const Value& value); static bool hasCommentForValue(const Value& value);
static String normalizeEOL(const String& text); static String normalizeEOL(const String& text);
typedef std::vector<String> ChildValues; using ChildValues = std::vector<String>;
ChildValues childValues_; ChildValues childValues_;
OStream* document_; OStream* document_;

View File

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

5
meson_options.txt Normal file
View File

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

View File

@@ -1,7 +1,7 @@
prefix=@CMAKE_INSTALL_PREFIX@ prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@ libdir=@libdir_for_pc_file@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@ includedir=@includedir_for_pc_file@
Name: jsoncpp Name: jsoncpp
Description: A C++ library for interacting with JSON Description: A C++ library for interacting with JSON

View File

@@ -1,6 +1,6 @@
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
# The new Python3 module is much more robust than the previous PythonInterp # The new Python3 module is much more robust than the previous PythonInterp
find_package (Python3 COMPONENTS Interpreter) find_package(Python3 COMPONENTS Interpreter)
# Set variables for backwards compatibility with cmake < 3.12.0 # Set variables for backwards compatibility with cmake < 3.12.0
set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND}) set(PYTHONINTERP_FOUND ${Python3_Interpreter_FOUND})
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE}) set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
@@ -11,16 +11,18 @@ endif()
add_executable(jsontestrunner_exe add_executable(jsontestrunner_exe
main.cpp main.cpp
) )
if(BUILD_SHARED_LIBS) if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0) if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL ) add_compile_definitions( JSON_DLL )
else() else()
add_definitions( -DJSON_DLL ) add_definitions(-DJSON_DLL)
endif() endif()
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
else()
target_link_libraries(jsontestrunner_exe jsoncpp_static)
endif() endif()
target_link_libraries(jsontestrunner_exe jsoncpp_lib)
set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe) set_target_properties(jsontestrunner_exe PROPERTIES OUTPUT_NAME jsontestrunner_exe)

View File

@@ -57,10 +57,10 @@ static Json::String readInputTestFile(const char* path) {
if (!file) if (!file)
return ""; return "";
fseek(file, 0, SEEK_END); fseek(file, 0, SEEK_END);
long const size = ftell(file); auto const size = ftell(file);
size_t const usize = static_cast<unsigned long>(size); auto const usize = static_cast<size_t>(size);
fseek(file, 0, SEEK_SET); fseek(file, 0, SEEK_SET);
char* buffer = new char[size + 1]; auto buffer = new char[size + 1];
buffer[size] = 0; buffer[size] = 0;
Json::String text; Json::String text;
if (fread(buffer, 1, usize, file) == usize) if (fread(buffer, 1, usize, file) == usize)
@@ -111,7 +111,7 @@ static void printValueTree(FILE* fout, Json::Value& value,
Json::Value::Members members(value.getMemberNames()); Json::Value::Members members(value.getMemberNames());
std::sort(members.begin(), members.end()); std::sort(members.begin(), members.end());
Json::String suffix = *(path.end() - 1) == '.' ? "" : "."; Json::String suffix = *(path.end() - 1) == '.' ? "" : ".";
for (auto name : members) { for (const auto& name : members) {
printValueTree(fout, value[name], path + suffix + name); printValueTree(fout, value[name], path + suffix + name);
} }
} break; } break;

View File

@@ -1,13 +1,7 @@
if( CMAKE_COMPILER_IS_GNUCXX ) if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 4.1.2)
#Get compiler version.
execute_process( COMMAND ${CMAKE_CXX_COMPILER} -dumpversion
OUTPUT_VARIABLE GNUCXX_VERSION )
#-Werror=* was introduced -after- GCC 4.1.2 #-Werror=* was introduced -after- GCC 4.1.2
if( GNUCXX_VERSION VERSION_GREATER 4.1.2 ) add_compile_options("-Werror=strict-aliasing")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=strict-aliasing") endif()
endif()
endif( CMAKE_COMPILER_IS_GNUCXX )
include(CheckIncludeFileCXX) include(CheckIncludeFileCXX)
include(CheckTypeSize) include(CheckTypeSize)
@@ -41,9 +35,9 @@ if(NOT (HAVE_CLOCALE AND HAVE_LCONV_SIZE AND HAVE_DECIMAL_POINT AND HAVE_LOCALEC
endif() endif()
endif() endif()
set( JSONCPP_INCLUDE_DIR ../../include ) set(JSONCPP_INCLUDE_DIR ../../include)
set( PUBLIC_HEADERS set(PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/config.h ${JSONCPP_INCLUDE_DIR}/json/config.h
${JSONCPP_INCLUDE_DIR}/json/forwards.h ${JSONCPP_INCLUDE_DIR}/json/forwards.h
${JSONCPP_INCLUDE_DIR}/json/json_features.h ${JSONCPP_INCLUDE_DIR}/json/json_features.h
@@ -52,49 +46,29 @@ set( PUBLIC_HEADERS
${JSONCPP_INCLUDE_DIR}/json/version.h ${JSONCPP_INCLUDE_DIR}/json/version.h
${JSONCPP_INCLUDE_DIR}/json/writer.h ${JSONCPP_INCLUDE_DIR}/json/writer.h
${JSONCPP_INCLUDE_DIR}/json/assertions.h ${JSONCPP_INCLUDE_DIR}/json/assertions.h
) )
source_group( "Public API" FILES ${PUBLIC_HEADERS} ) source_group("Public API" FILES ${PUBLIC_HEADERS})
set(jsoncpp_sources set(JSONCPP_SOURCES
json_tool.h json_tool.h
json_reader.cpp json_reader.cpp
json_valueiterator.inl json_valueiterator.inl
json_value.cpp json_value.cpp
json_writer.cpp) json_writer.cpp
)
# Install instructions for this target # Install instructions for this target
if(JSONCPP_WITH_CMAKE_PACKAGE) if(JSONCPP_WITH_CMAKE_PACKAGE)
set(INSTALL_EXPORT EXPORT jsoncpp) set(INSTALL_EXPORT EXPORT jsoncpp)
else(JSONCPP_WITH_CMAKE_PACKAGE) else()
set(INSTALL_EXPORT) set(INSTALL_EXPORT)
endif() endif()
if(BUILD_SHARED_LIBS)
if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions( JSON_DLL_BUILD )
else()
add_definitions( -DJSON_DLL_BUILD )
endif()
endif()
add_library(jsoncpp_lib ${PUBLIC_HEADERS} ${jsoncpp_sources})
set_target_properties( jsoncpp_lib PROPERTIES VERSION ${JSONCPP_VERSION} SOVERSION ${JSONCPP_SOVERSION})
set_target_properties( jsoncpp_lib PROPERTIES OUTPUT_NAME jsoncpp
DEBUG_OUTPUT_NAME jsoncpp${DEBUG_LIBNAME_SUFFIX} )
set_target_properties( jsoncpp_lib PROPERTIES POSITION_INDEPENDENT_CODE ON)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties( jsoncpp_lib PROPERTIES INSTALL_RPATH "@loader_path/." )
endif()
# Specify compiler features required when compiling a given target. # Specify compiler features required when compiling a given target.
# See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES # See https://cmake.org/cmake/help/v3.1/prop_gbl/CMAKE_CXX_KNOWN_FEATURES.html#prop_gbl:CMAKE_CXX_KNOWN_FEATURES
# for complete list of features available # for complete list of features available
target_compile_features(jsoncpp_lib PUBLIC list(APPEND REQUIRED_FEATURES
cxx_std_11 # Compiler mode is aware of C++ 11. cxx_std_11 # Compiler mode is aware of C++ 11.
#MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341. #MSVC 1900 cxx_alignas # Alignment control alignas, as defined in N2341.
#MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341. #MSVC 1900 cxx_alignof # Alignment control alignof, as defined in N2341.
@@ -141,14 +115,106 @@ target_compile_features(jsoncpp_lib PUBLIC
cxx_variadic_templates # Variadic templates, as defined in N2242. cxx_variadic_templates # Variadic templates, as defined in N2242.
) )
install( TARGETS jsoncpp_lib ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11) if(BUILD_SHARED_LIBS)
target_include_directories( jsoncpp_lib PUBLIC if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.12.0)
add_compile_definitions(JSON_DLL_BUILD)
else()
add_definitions(-DJSON_DLL_BUILD)
endif()
set(SHARED_LIB ${PROJECT_NAME}_lib)
add_library(${SHARED_LIB} SHARED ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
set_target_properties(${SHARED_LIB} PROPERTIES
OUTPUT_NAME jsoncpp
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}
POSITION_INDEPENDENT_CODE ON
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${SHARED_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${SHARED_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${SHARED_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}> $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}> $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>) $<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${SHARED_LIB})
endif() endif()
if(BUILD_STATIC_LIBS)
set(STATIC_LIB ${PROJECT_NAME}_static)
add_library(${STATIC_LIB} STATIC ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
# avoid name clashes on windows as the shared import lib is alse named jsoncpp.lib
if(NOT DEFINED STATIC_SUFFIX AND BUILD_SHARED_LIBS)
set(STATIC_SUFFIX "_static")
endif()
set_target_properties(${STATIC_LIB} PROPERTIES
OUTPUT_NAME jsoncpp${STATIC_SUFFIX}
VERSION ${PROJECT_VERSION}
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${STATIC_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${STATIC_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${STATIC_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${STATIC_LIB})
endif()
if(BUILD_OBJECT_LIBS)
set(OBJECT_LIB ${PROJECT_NAME}_object)
add_library(${OBJECT_LIB} OBJECT ${PUBLIC_HEADERS} ${JSONCPP_SOURCES})
set_target_properties(${OBJECT_LIB} PROPERTIES
OUTPUT_NAME jsoncpp
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_SOVERSION}
POSITION_INDEPENDENT_CODE ON
)
# Set library's runtime search path on OSX
if(APPLE)
set_target_properties(${OBJECT_LIB} PROPERTIES INSTALL_RPATH "@loader_path/.")
endif()
target_compile_features(${OBJECT_LIB} PUBLIC ${REQUIRED_FEATURES})
if(NOT CMAKE_VERSION VERSION_LESS 2.8.11)
target_include_directories(${OBJECT_LIB} PUBLIC
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/${JSONCPP_INCLUDE_DIR}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/json>
)
endif()
list(APPEND CMAKE_TARGETS ${OBJECT_LIB})
endif()
install(TARGETS ${CMAKE_TARGETS} ${INSTALL_EXPORT}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
OBJECTS DESTINATION ${CMAKE_INSTALL_LIBDIR}
)

View File

@@ -10,6 +10,7 @@
#include <json/reader.h> #include <json/reader.h>
#include <json/value.h> #include <json/value.h>
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <iostream> #include <iostream>
@@ -54,7 +55,7 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using CharReaderPtr = std::unique_ptr<CharReader>; using CharReaderPtr = std::unique_ptr<CharReader>;
#else #else
typedef std::auto_ptr<CharReader> CharReaderPtr; using CharReaderPtr = std::auto_ptr<CharReader>;
#endif #endif
// Implementation of class Features // Implementation of class Features
@@ -77,10 +78,7 @@ Features Features::strictMode() {
// //////////////////////////////// // ////////////////////////////////
bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) { bool Reader::containsNewLine(Reader::Location begin, Reader::Location end) {
for (; begin < end; ++begin) return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
if (*begin == '\n' || *begin == '\r')
return true;
return false;
} }
// Class Reader // Class Reader
@@ -464,7 +462,7 @@ bool Reader::readObject(Token& token) {
Value numberName; Value numberName;
if (!decodeNumber(tokenName, numberName)) if (!decodeNumber(tokenName, numberName))
return recoverFromError(tokenObjectEnd); return recoverFromError(tokenObjectEnd);
name = String(numberName.asCString()); name = numberName.asString();
} else { } else {
break; break;
} }
@@ -629,7 +627,7 @@ bool Reader::decodeString(Token& token, String& decoded) {
Char c = *current++; Char c = *current++;
if (c == '"') if (c == '"')
break; break;
else if (c == '\\') { if (c == '\\') {
if (current == end) if (current == end)
return addError("Empty escape sequence in string", token, current); return addError("Empty escape sequence in string", token, current);
Char escape = *current++; Char escape = *current++;
@@ -863,6 +861,7 @@ class OurFeatures {
public: public:
static OurFeatures all(); static OurFeatures all();
bool allowComments_; bool allowComments_;
bool allowTrailingCommas_;
bool strictRoot_; bool strictRoot_;
bool allowDroppedNullPlaceholders_; bool allowDroppedNullPlaceholders_;
bool allowNumericKeys_; bool allowNumericKeys_;
@@ -870,6 +869,7 @@ public:
bool failIfExtra_; bool failIfExtra_;
bool rejectDupKeys_; bool rejectDupKeys_;
bool allowSpecialFloats_; bool allowSpecialFloats_;
bool skipBom_;
size_t stackLimit_; size_t stackLimit_;
}; // OurFeatures }; // OurFeatures
@@ -938,6 +938,7 @@ private:
bool readToken(Token& token); bool readToken(Token& token);
void skipSpaces(); void skipSpaces();
void skipBom(bool skipBom);
bool match(const Char* pattern, int patternLength); bool match(const Char* pattern, int patternLength);
bool readComment(); bool readComment();
bool readCStyleComment(bool* containsNewLineResult); bool readCStyleComment(bool* containsNewLineResult);
@@ -995,10 +996,7 @@ private:
bool OurReader::containsNewLine(OurReader::Location begin, bool OurReader::containsNewLine(OurReader::Location begin,
OurReader::Location end) { OurReader::Location end) {
for (; begin < end; ++begin) return std::any_of(begin, end, [](char b) { return b == '\n' || b == '\r'; });
if (*begin == '\n' || *begin == '\r')
return true;
return false;
} }
OurReader::OurReader(OurFeatures const& features) : features_(features) {} OurReader::OurReader(OurFeatures const& features) : features_(features) {}
@@ -1021,6 +1019,8 @@ bool OurReader::parse(const char* beginDoc, const char* endDoc, Value& root,
nodes_.pop(); nodes_.pop();
nodes_.push(&root); nodes_.push(&root);
// skip byte order mark if it exists at the beginning of the UTF-8 text.
skipBom(features_.skipBom_);
bool successful = readValue(); bool successful = readValue();
nodes_.pop(); nodes_.pop();
Token token; Token token;
@@ -1175,8 +1175,11 @@ bool OurReader::readToken(Token& token) {
if (features_.allowSingleQuotes_) { if (features_.allowSingleQuotes_) {
token.type_ = tokenString; token.type_ = tokenString;
ok = readStringSingleQuote(); ok = readStringSingleQuote();
} else {
// If we don't allow single quotes, this is a failure case.
ok = false;
}
break; break;
} // else fall through
case '/': case '/':
token.type_ = tokenComment; token.type_ = tokenComment;
ok = readComment(); ok = readComment();
@@ -1267,6 +1270,16 @@ void OurReader::skipSpaces() {
} }
} }
void OurReader::skipBom(bool skipBom) {
// The default behavior is to skip BOM.
if (skipBom) {
if ((end_ - begin_) >= 3 && strncmp(begin_, "\xEF\xBB\xBF", 3) == 0) {
begin_ += 3;
current_ = begin_;
}
}
}
bool OurReader::match(const Char* pattern, int patternLength) { bool OurReader::match(const Char* pattern, int patternLength) {
if (end_ - current_ < patternLength) if (end_ - current_ < patternLength)
return false; return false;
@@ -1349,12 +1362,11 @@ bool OurReader::readCStyleComment(bool* containsNewLineResult) {
while ((current_ + 1) < end_) { while ((current_ + 1) < end_) {
Char c = getNextChar(); Char c = getNextChar();
if (c == '*' && *current_ == '/') { if (c == '*' && *current_ == '/')
break; break;
} else if (c == '\n') { if (c == '\n')
*containsNewLineResult = true; *containsNewLineResult = true;
} }
}
return getNextChar() == '/'; return getNextChar() == '/';
} }
@@ -1437,7 +1449,9 @@ bool OurReader::readObject(Token& token) {
initialTokenOk = readToken(tokenName); initialTokenOk = readToken(tokenName);
if (!initialTokenOk) if (!initialTokenOk)
break; break;
if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object if (tokenName.type_ == tokenObjectEnd &&
(name.empty() ||
features_.allowTrailingCommas_)) // empty object or trailing comma
return true; return true;
name.clear(); name.clear();
if (tokenName.type_ == tokenString) { if (tokenName.type_ == tokenString) {
@@ -1491,15 +1505,19 @@ bool OurReader::readArray(Token& token) {
Value init(arrayValue); Value init(arrayValue);
currentValue().swapPayload(init); currentValue().swapPayload(init);
currentValue().setOffsetStart(token.start_ - begin_); currentValue().setOffsetStart(token.start_ - begin_);
int index = 0;
for (;;) {
skipSpaces(); skipSpaces();
if (current_ != end_ && *current_ == ']') // empty array if (current_ != end_ && *current_ == ']' &&
(index == 0 ||
(features_.allowTrailingCommas_ &&
!features_.allowDroppedNullPlaceholders_))) // empty array or trailing
// comma
{ {
Token endArray; Token endArray;
readToken(endArray); readToken(endArray);
return true; return true;
} }
int index = 0;
for (;;) {
Value& value = currentValue()[index++]; Value& value = currentValue()[index++];
nodes_.push(&value); nodes_.push(&value);
bool ok = readValue(); bool ok = readValue();
@@ -1571,9 +1589,9 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
// then take the inverse. This assumes that minLargestInt is only a single // then take the inverse. This assumes that minLargestInt is only a single
// power of 10 different in magnitude, which we check above. For the last // power of 10 different in magnitude, which we check above. For the last
// digit, we take the modulus before negating for the same reason. // digit, we take the modulus before negating for the same reason.
static constexpr Value::LargestUInt negative_threshold = static constexpr auto negative_threshold =
Value::LargestUInt(-(Value::minLargestInt / 10)); Value::LargestUInt(-(Value::minLargestInt / 10));
static constexpr Value::UInt negative_last_digit = static constexpr auto negative_last_digit =
Value::UInt(-(Value::minLargestInt % 10)); Value::UInt(-(Value::minLargestInt % 10));
const Value::LargestUInt threshold = const Value::LargestUInt threshold =
@@ -1587,7 +1605,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
if (c < '0' || c > '9') if (c < '0' || c > '9')
return decodeDouble(token, decoded); return decodeDouble(token, decoded);
const Value::UInt digit(static_cast<Value::UInt>(c - '0')); const auto digit(static_cast<Value::UInt>(c - '0'));
if (value >= threshold) { if (value >= threshold) {
// We've hit or exceeded the max value divided by 10 (rounded down). If // We've hit or exceeded the max value divided by 10 (rounded down). If
// a) we've only just touched the limit, meaing value == threshold, // a) we've only just touched the limit, meaing value == threshold,
@@ -1604,7 +1622,7 @@ bool OurReader::decodeNumber(Token& token, Value& decoded) {
if (isNegative) { if (isNegative) {
// We use the same magnitude assumption here, just in case. // We use the same magnitude assumption here, just in case.
const Value::UInt last_digit = static_cast<Value::UInt>(value % 10); const auto last_digit = static_cast<Value::UInt>(value % 10);
decoded = -Value::LargestInt(value / 10) * 10 - last_digit; decoded = -Value::LargestInt(value / 10) * 10 - last_digit;
} else if (value <= Value::LargestUInt(Value::maxLargestInt)) { } else if (value <= Value::LargestUInt(Value::maxLargestInt)) {
decoded = Value::LargestInt(value); decoded = Value::LargestInt(value);
@@ -1654,9 +1672,9 @@ bool OurReader::decodeString(Token& token, String& decoded) {
Location end = token.end_ - 1; // do not include '"' Location end = token.end_ - 1; // do not include '"'
while (current != end) { while (current != end) {
Char c = *current++; Char c = *current++;
if (c == '"') { if (c == '"')
break; break;
} else if (c == '\\') { if (c == '\\') {
if (current == end) if (current == end)
return addError("Empty escape sequence in string", token, current); return addError("Empty escape sequence in string", token, current);
Char escape = *current++; Char escape = *current++;
@@ -1866,6 +1884,7 @@ CharReader* CharReaderBuilder::newCharReader() const {
bool collectComments = settings_["collectComments"].asBool(); bool collectComments = settings_["collectComments"].asBool();
OurFeatures features = OurFeatures::all(); OurFeatures features = OurFeatures::all();
features.allowComments_ = settings_["allowComments"].asBool(); features.allowComments_ = settings_["allowComments"].asBool();
features.allowTrailingCommas_ = settings_["allowTrailingCommas"].asBool();
features.strictRoot_ = settings_["strictRoot"].asBool(); features.strictRoot_ = settings_["strictRoot"].asBool();
features.allowDroppedNullPlaceholders_ = features.allowDroppedNullPlaceholders_ =
settings_["allowDroppedNullPlaceholders"].asBool(); settings_["allowDroppedNullPlaceholders"].asBool();
@@ -1878,38 +1897,37 @@ CharReader* CharReaderBuilder::newCharReader() const {
features.failIfExtra_ = settings_["failIfExtra"].asBool(); features.failIfExtra_ = settings_["failIfExtra"].asBool();
features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool(); features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool(); features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
features.skipBom_ = settings_["skipBom"].asBool();
return new OurCharReader(collectComments, features); return new OurCharReader(collectComments, features);
} }
static void getValidReaderKeys(std::set<String>* valid_keys) {
valid_keys->clear();
valid_keys->insert("collectComments");
valid_keys->insert("allowComments");
valid_keys->insert("strictRoot");
valid_keys->insert("allowDroppedNullPlaceholders");
valid_keys->insert("allowNumericKeys");
valid_keys->insert("allowSingleQuotes");
valid_keys->insert("stackLimit");
valid_keys->insert("failIfExtra");
valid_keys->insert("rejectDupKeys");
valid_keys->insert("allowSpecialFloats");
}
bool CharReaderBuilder::validate(Json::Value* invalid) const { bool CharReaderBuilder::validate(Json::Value* invalid) const {
Json::Value my_invalid; static const auto& valid_keys = *new std::set<String>{
if (!invalid) "collectComments",
invalid = &my_invalid; // so we do not need to test for NULL "allowComments",
Json::Value& inv = *invalid; "allowTrailingCommas",
std::set<String> valid_keys; "strictRoot",
getValidReaderKeys(&valid_keys); "allowDroppedNullPlaceholders",
Value::Members keys = settings_.getMemberNames(); "allowNumericKeys",
size_t n = keys.size(); "allowSingleQuotes",
for (size_t i = 0; i < n; ++i) { "stackLimit",
String const& key = keys[i]; "failIfExtra",
if (valid_keys.find(key) == valid_keys.end()) { "rejectDupKeys",
inv[key] = settings_[key]; "allowSpecialFloats",
"skipBom",
};
for (auto si = settings_.begin(); si != settings_.end(); ++si) {
auto key = si.name();
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
else
return false;
} }
} return invalid ? invalid->empty() : true;
return inv.empty();
} }
Value& CharReaderBuilder::operator[](const String& key) { Value& CharReaderBuilder::operator[](const String& key) {
return settings_[key]; return settings_[key];
} }
@@ -1917,6 +1935,7 @@ Value& CharReaderBuilder::operator[](const String& key) {
void CharReaderBuilder::strictMode(Json::Value* settings) { void CharReaderBuilder::strictMode(Json::Value* settings) {
//! [CharReaderBuilderStrictMode] //! [CharReaderBuilderStrictMode]
(*settings)["allowComments"] = false; (*settings)["allowComments"] = false;
(*settings)["allowTrailingCommas"] = false;
(*settings)["strictRoot"] = true; (*settings)["strictRoot"] = true;
(*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false; (*settings)["allowNumericKeys"] = false;
@@ -1925,6 +1944,7 @@ void CharReaderBuilder::strictMode(Json::Value* settings) {
(*settings)["failIfExtra"] = true; (*settings)["failIfExtra"] = true;
(*settings)["rejectDupKeys"] = true; (*settings)["rejectDupKeys"] = true;
(*settings)["allowSpecialFloats"] = false; (*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderStrictMode] //! [CharReaderBuilderStrictMode]
} }
// static // static
@@ -1932,6 +1952,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
//! [CharReaderBuilderDefaults] //! [CharReaderBuilderDefaults]
(*settings)["collectComments"] = true; (*settings)["collectComments"] = true;
(*settings)["allowComments"] = true; (*settings)["allowComments"] = true;
(*settings)["allowTrailingCommas"] = true;
(*settings)["strictRoot"] = false; (*settings)["strictRoot"] = false;
(*settings)["allowDroppedNullPlaceholders"] = false; (*settings)["allowDroppedNullPlaceholders"] = false;
(*settings)["allowNumericKeys"] = false; (*settings)["allowNumericKeys"] = false;
@@ -1940,6 +1961,7 @@ void CharReaderBuilder::setDefaults(Json::Value* settings) {
(*settings)["failIfExtra"] = false; (*settings)["failIfExtra"] = false;
(*settings)["rejectDupKeys"] = false; (*settings)["rejectDupKeys"] = false;
(*settings)["allowSpecialFloats"] = false; (*settings)["allowSpecialFloats"] = false;
(*settings)["skipBom"] = true;
//! [CharReaderBuilderDefaults] //! [CharReaderBuilderDefaults]
} }

View File

@@ -71,7 +71,7 @@ enum {
}; };
// Defines a char buffer for use with uintToString(). // Defines a char buffer for use with uintToString().
typedef char UIntToStringBuffer[uintToStringBufferSize]; using UIntToStringBuffer = char[uintToStringBufferSize];
/** Converts an unsigned integer to string. /** Converts an unsigned integer to string.
* @param value Unsigned integer to convert to string * @param value Unsigned integer to convert to string

View File

@@ -8,16 +8,14 @@
#include <json/value.h> #include <json/value.h>
#include <json/writer.h> #include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <cstddef>
#include <cstring> #include <cstring>
#include <iostream>
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#ifdef JSON_USE_CPPTL
#include <cpptl/conststring.h>
#endif
#include <algorithm> // min()
#include <cstddef> // size_t
// Provide implementation equivalent of std::snprintf for older _MSC compilers // Provide implementation equivalent of std::snprintf for older _MSC compilers
#if defined(_MSC_VER) && _MSC_VER < 1900 #if defined(_MSC_VER) && _MSC_VER < 1900
@@ -120,7 +118,7 @@ static inline char* duplicateStringValue(const char* value, size_t length) {
if (length >= static_cast<size_t>(Value::maxInt)) if (length >= static_cast<size_t>(Value::maxInt))
length = Value::maxInt - 1; length = Value::maxInt - 1;
char* newString = static_cast<char*>(malloc(length + 1)); auto newString = static_cast<char*>(malloc(length + 1));
if (newString == nullptr) { if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateStringValue(): " throwRuntimeError("in Json::Value::duplicateStringValue(): "
"Failed to allocate string value buffer"); "Failed to allocate string value buffer");
@@ -140,8 +138,8 @@ static inline char* duplicateAndPrefixStringValue(const char* value,
sizeof(unsigned) - 1U, sizeof(unsigned) - 1U,
"in Json::Value::duplicateAndPrefixStringValue(): " "in Json::Value::duplicateAndPrefixStringValue(): "
"length too big for prefixing"); "length too big for prefixing");
unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U; size_t actualLength = sizeof(length) + length + 1;
char* newString = static_cast<char*>(malloc(actualLength)); auto newString = static_cast<char*>(malloc(actualLength));
if (newString == nullptr) { if (newString == nullptr) {
throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): " throwRuntimeError("in Json::Value::duplicateAndPrefixStringValue(): "
"Failed to allocate string value buffer"); "Failed to allocate string value buffer");
@@ -203,8 +201,8 @@ namespace Json {
#if JSON_USE_EXCEPTION #if JSON_USE_EXCEPTION
Exception::Exception(String msg) : msg_(std::move(msg)) {} Exception::Exception(String msg) : msg_(std::move(msg)) {}
Exception::~Exception() JSONCPP_NOEXCEPT = default; Exception::~Exception() noexcept = default;
char const* Exception::what() const JSONCPP_NOEXCEPT { return msg_.c_str(); } char const* Exception::what() const noexcept { return msg_.c_str(); }
RuntimeError::RuntimeError(String const& msg) : Exception(msg) {} RuntimeError::RuntimeError(String const& msg) : Exception(msg) {}
LogicError::LogicError(String const& msg) : Exception(msg) {} LogicError::LogicError(String const& msg) : Exception(msg) {}
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
@@ -214,8 +212,14 @@ JSONCPP_NORETURN void throwLogicError(String const& msg) {
throw LogicError(msg); throw LogicError(msg);
} }
#else // !JSON_USE_EXCEPTION #else // !JSON_USE_EXCEPTION
JSONCPP_NORETURN void throwRuntimeError(String const& msg) { abort(); } JSONCPP_NORETURN void throwRuntimeError(String const& msg) {
JSONCPP_NORETURN void throwLogicError(String const& msg) { abort(); } std::cerr << msg << std::endl;
abort();
}
JSONCPP_NORETURN void throwLogicError(String const& msg) {
std::cerr << msg << std::endl;
abort();
}
#endif #endif
// ////////////////////////////////////////////////////////////////// // //////////////////////////////////////////////////////////////////
@@ -419,14 +423,6 @@ Value::Value(const StaticString& value) {
value_.string_ = const_cast<char*>(value.c_str()); value_.string_ = const_cast<char*>(value.c_str());
} }
#ifdef JSON_USE_CPPTL
Value::Value(const CppTL::ConstString& value) {
initBasic(stringValue, true);
value_.string_ = duplicateAndPrefixStringValue(
value, static_cast<unsigned>(value.length()));
}
#endif
Value::Value(bool value) { Value::Value(bool value) {
initBasic(booleanValue); initBasic(booleanValue);
value_.bool_ = value; value_.bool_ = value;
@@ -529,9 +525,10 @@ bool Value::operator<(const Value& other) const {
} }
case arrayValue: case arrayValue:
case objectValue: { case objectValue: {
int delta = int(value_.map_->size() - other.value_.map_->size()); auto thisSize = value_.map_->size();
if (delta) auto otherSize = other.value_.map_->size();
return delta < 0; if (thisSize != otherSize)
return thisSize < otherSize;
return (*value_.map_) < (*other.value_.map_); return (*value_.map_) < (*other.value_.map_);
} }
default: default:
@@ -654,15 +651,6 @@ String Value::asString() const {
} }
} }
#ifdef JSON_USE_CPPTL
CppTL::ConstString Value::asConstString() const {
unsigned len;
char const* str;
decodePrefixedString(isAllocated(), value_.string_, &len, &str);
return CppTL::ConstString(str, len);
}
#endif
Value::Int Value::asInt() const { Value::Int Value::asInt() const {
switch (type()) { switch (type()) {
case intValue: case intValue:
@@ -894,7 +882,6 @@ ArrayIndex Value::size() const {
bool Value::empty() const { bool Value::empty() const {
if (isNull() || isArray() || isObject()) if (isNull() || isArray() || isObject())
return size() == 0U; return size() == 0U;
else
return false; return false;
} }
@@ -1135,18 +1122,6 @@ Value& Value::operator[](const StaticString& key) {
return resolveReference(key.c_str()); return resolveReference(key.c_str());
} }
#ifdef JSON_USE_CPPTL
Value& Value::operator[](const CppTL::ConstString& key) {
return resolveReference(key.c_str(), key.end_c_str());
}
Value const& Value::operator[](CppTL::ConstString const& key) const {
Value const* found = find(key.c_str(), key.end_c_str());
if (!found)
return nullSingleton();
return *found;
}
#endif
Value& Value::append(const Value& value) { return append(Value(value)); } Value& Value::append(const Value& value) { return append(Value(value)); }
Value& Value::append(Value&& value) { Value& Value::append(Value&& value) {
@@ -1158,19 +1133,22 @@ Value& Value::append(Value&& value) {
return this->value_.map_->emplace(size(), std::move(value)).first->second; return this->value_.map_->emplace(size(), std::move(value)).first->second;
} }
bool Value::insert(ArrayIndex index, Value newValue) { bool Value::insert(ArrayIndex index, const Value& newValue) {
return insert(index, Value(newValue));
}
bool Value::insert(ArrayIndex index, Value&& newValue) {
JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue, JSON_ASSERT_MESSAGE(type() == nullValue || type() == arrayValue,
"in Json::Value::insert: requires arrayValue"); "in Json::Value::insert: requires arrayValue");
ArrayIndex length = size(); ArrayIndex length = size();
if (index > length) { if (index > length) {
return false; return false;
} else { }
for (ArrayIndex i = length; i > index; i--) { for (ArrayIndex i = length; i > index; i--) {
(*this)[i] = std::move((*this)[i - 1]); (*this)[i] = std::move((*this)[i - 1]);
} }
(*this)[index] = std::move(newValue); (*this)[index] = std::move(newValue);
return true; return true;
}
} }
Value Value::get(char const* begin, char const* end, Value Value::get(char const* begin, char const* end,
@@ -1240,13 +1218,6 @@ bool Value::removeIndex(ArrayIndex index, Value* removed) {
return true; return true;
} }
#ifdef JSON_USE_CPPTL
Value Value::get(const CppTL::ConstString& key,
const Value& defaultValue) const {
return get(key.c_str(), key.end_c_str(), defaultValue);
}
#endif
bool Value::isMember(char const* begin, char const* end) const { bool Value::isMember(char const* begin, char const* end) const {
Value const* value = find(begin, end); Value const* value = find(begin, end);
return nullptr != value; return nullptr != value;
@@ -1258,12 +1229,6 @@ bool Value::isMember(String const& key) const {
return isMember(key.data(), key.data() + key.length()); return isMember(key.data(), key.data() + key.length());
} }
#ifdef JSON_USE_CPPTL
bool Value::isMember(const CppTL::ConstString& key) const {
return isMember(key.c_str(), key.end_c_str());
}
#endif
Value::Members Value::getMemberNames() const { Value::Members Value::getMemberNames() const {
JSON_ASSERT_MESSAGE( JSON_ASSERT_MESSAGE(
type() == nullValue || type() == objectValue, type() == nullValue || type() == objectValue,
@@ -1279,31 +1244,6 @@ Value::Members Value::getMemberNames() const {
} }
return members; return members;
} }
//
//# ifdef JSON_USE_CPPTL
// EnumMemberNames
// Value::enumMemberNames() const
//{
// if ( type() == objectValue )
// {
// return CppTL::Enum::any( CppTL::Enum::transform(
// CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
// MemberNamesTransform() ) );
// }
// return EnumMemberNames();
//}
//
//
// EnumValues
// Value::enumValues() const
//{
// if ( type() == objectValue || type() == arrayValue )
// return CppTL::Enum::anyValues( *(value_.map_),
// CppTL::Type<const Value &>() );
// return EnumValues();
//}
//
//# endif
static bool IsIntegral(double d) { static bool IsIntegral(double d) {
double integral_part; double integral_part;

View File

@@ -30,9 +30,6 @@ void ValueIteratorBase::decrement() { --current_; }
ValueIteratorBase::difference_type ValueIteratorBase::difference_type
ValueIteratorBase::computeDistance(const SelfType& other) const { ValueIteratorBase::computeDistance(const SelfType& other) const {
#ifdef JSON_USE_CPPTL_SMALLMAP
return other.current_ - current_;
#else
// Iterator for null value are initialized using the default // Iterator for null value are initialized using the default
// constructor, which initialize current_ to the default // constructor, which initialize current_ to the default
// std::map::iterator. As begin() and end() are two instance // std::map::iterator. As begin() and end() are two instance
@@ -53,7 +50,6 @@ ValueIteratorBase::computeDistance(const SelfType& other) const {
++myDistance; ++myDistance;
} }
return myDistance; return myDistance;
#endif
} }
bool ValueIteratorBase::isEqual(const SelfType& other) const { bool ValueIteratorBase::isEqual(const SelfType& other) const {

View File

@@ -7,7 +7,9 @@
#include "json_tool.h" #include "json_tool.h"
#include <json/writer.h> #include <json/writer.h>
#endif // if !defined(JSON_IS_AMALGAMATION) #endif // if !defined(JSON_IS_AMALGAMATION)
#include <algorithm>
#include <cassert> #include <cassert>
#include <cctype>
#include <cstring> #include <cstring>
#include <iomanip> #include <iomanip>
#include <memory> #include <memory>
@@ -86,7 +88,7 @@ namespace Json {
#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520) #if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
using StreamWriterPtr = std::unique_ptr<StreamWriter>; using StreamWriterPtr = std::unique_ptr<StreamWriter>;
#else #else
typedef std::auto_ptr<StreamWriter> StreamWriterPtr; using StreamWriterPtr = std::auto_ptr<StreamWriter>;
#endif #endif
String valueToString(LargestInt value) { String valueToString(LargestInt value) {
@@ -173,16 +175,12 @@ String valueToString(double value, unsigned int precision,
String valueToString(bool value) { return value ? "true" : "false"; } String valueToString(bool value) { return value ? "true" : "false"; }
static bool isAnyCharRequiredQuoting(char const* s, size_t n) { static bool doesAnyCharRequireEscaping(char const* s, size_t n) {
assert(s || !n); assert(s || !n);
char const* const end = s + n; return std::any_of(s, s + n, [](unsigned char c) {
for (char const* cur = s; cur < end; ++cur) { return c == '\\' || c == '"' || c < 0x20 || c > 0x7F;
if (*cur == '\\' || *cur == '\"' || *cur < ' ' || });
static_cast<unsigned char>(*cur) < 0x80)
return true;
}
return false;
} }
static unsigned int utf8ToCodepoint(const char*& s, const char* e) { static unsigned int utf8ToCodepoint(const char*& s, const char* e) {
@@ -264,12 +262,20 @@ static String toHex16Bit(unsigned int x) {
return result; return result;
} }
static void appendRaw(String& result, unsigned ch) {
result += static_cast<char>(ch);
}
static void appendHex(String& result, unsigned ch) {
result.append("\\u").append(toHex16Bit(ch));
}
static String valueToQuotedStringN(const char* value, unsigned length, static String valueToQuotedStringN(const char* value, unsigned length,
bool emitUTF8 = false) { bool emitUTF8 = false) {
if (value == nullptr) if (value == nullptr)
return ""; return "";
if (!isAnyCharRequiredQuoting(value, length)) if (!doesAnyCharRequireEscaping(value, length))
return String("\"") + value + "\""; return String("\"") + value + "\"";
// We have to walk value and escape any special characters. // We have to walk value and escape any special characters.
// Appending to String is not efficient, but this should be rare. // Appending to String is not efficient, but this should be rare.
@@ -312,29 +318,26 @@ static String valueToQuotedStringN(const char* value, unsigned length,
// sequence from occurring. // sequence from occurring.
default: { default: {
if (emitUTF8) { if (emitUTF8) {
result += *c; unsigned codepoint = static_cast<unsigned char>(*c);
if (codepoint < 0x20) {
appendHex(result, codepoint);
} else { } else {
unsigned int codepoint = utf8ToCodepoint(c, end); appendRaw(result, codepoint);
const unsigned int FIRST_NON_CONTROL_CODEPOINT = 0x20; }
const unsigned int LAST_NON_CONTROL_CODEPOINT = 0x7F; } else {
const unsigned int FIRST_SURROGATE_PAIR_CODEPOINT = 0x10000; unsigned codepoint = utf8ToCodepoint(c, end); // modifies `c`
// don't escape non-control characters if (codepoint < 0x20) {
// (short escape sequence are applied above) appendHex(result, codepoint);
if (FIRST_NON_CONTROL_CODEPOINT <= codepoint && } else if (codepoint < 0x80) {
codepoint <= LAST_NON_CONTROL_CODEPOINT) { appendRaw(result, codepoint);
result += static_cast<char>(codepoint); } else if (codepoint < 0x10000) {
} else if (codepoint < // Basic Multilingual Plane
FIRST_SURROGATE_PAIR_CODEPOINT) { // codepoint is in Basic appendHex(result, codepoint);
// Multilingual Plane } else {
result += "\\u"; // Extended Unicode. Encode 20 bits as a surrogate pair.
result += toHex16Bit(codepoint); codepoint -= 0x10000;
} else { // codepoint is not in Basic Multilingual Plane appendHex(result, 0xd800 + ((codepoint >> 10) & 0x3ff));
// convert to surrogate pair first appendHex(result, 0xdc00 + (codepoint & 0x3ff));
codepoint -= FIRST_SURROGATE_PAIR_CODEPOINT;
result += "\\u";
result += toHex16Bit((codepoint >> 10) + 0xD800);
result += "\\u";
result += toHex16Bit((codepoint & 0x3FF) + 0xDC00);
} }
} }
} break; } break;
@@ -1197,34 +1200,30 @@ StreamWriter* StreamWriterBuilder::newStreamWriter() const {
endingLineFeedSymbol, usf, emitUTF8, pre, endingLineFeedSymbol, usf, emitUTF8, pre,
precisionType); precisionType);
} }
static void getValidWriterKeys(std::set<String>* valid_keys) {
valid_keys->clear();
valid_keys->insert("indentation");
valid_keys->insert("commentStyle");
valid_keys->insert("enableYAMLCompatibility");
valid_keys->insert("dropNullPlaceholders");
valid_keys->insert("useSpecialFloats");
valid_keys->insert("emitUTF8");
valid_keys->insert("precision");
valid_keys->insert("precisionType");
}
bool StreamWriterBuilder::validate(Json::Value* invalid) const { bool StreamWriterBuilder::validate(Json::Value* invalid) const {
Json::Value my_invalid; static const auto& valid_keys = *new std::set<String>{
if (!invalid) "indentation",
invalid = &my_invalid; // so we do not need to test for NULL "commentStyle",
Json::Value& inv = *invalid; "enableYAMLCompatibility",
std::set<String> valid_keys; "dropNullPlaceholders",
getValidWriterKeys(&valid_keys); "useSpecialFloats",
Value::Members keys = settings_.getMemberNames(); "emitUTF8",
size_t n = keys.size(); "precision",
for (size_t i = 0; i < n; ++i) { "precisionType",
String const& key = keys[i]; };
if (valid_keys.find(key) == valid_keys.end()) { for (auto si = settings_.begin(); si != settings_.end(); ++si) {
inv[key] = settings_[key]; auto key = si.name();
if (valid_keys.count(key))
continue;
if (invalid)
(*invalid)[std::move(key)] = *si;
else
return false;
} }
} return invalid ? invalid->empty() : true;
return inv.empty();
} }
Value& StreamWriterBuilder::operator[](const String& key) { Value& StreamWriterBuilder::operator[](const String& key) {
return settings_[key]; return settings_[key];
} }

View File

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

View File

@@ -9,7 +9,6 @@
#include <json/config.h> #include <json/config.h>
#include <json/json.h> #include <json/json.h>
#include <memory> #include <memory>
#include <stdint.h>
#include <string> #include <string>
namespace Json { namespace Json {
@@ -40,11 +39,12 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7); builder.settings_["rejectDupKeys_"] = hash_settings & (1 << 7);
builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8); builder.settings_["allowSpecialFloats_"] = hash_settings & (1 << 8);
builder.settings_["collectComments"] = hash_settings & (1 << 9); builder.settings_["collectComments"] = hash_settings & (1 << 9);
builder.settings_["allowTrailingCommas_"] = hash_settings & (1 << 10);
std::unique_ptr<Json::CharReader> reader(builder.newCharReader()); std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
Json::Value root; Json::Value root;
const char* data_str = reinterpret_cast<const char*>(data); const auto data_str = reinterpret_cast<const char*>(data);
try { try {
reader->parse(data_str, data_str + size, &root, nullptr); reader->parse(data_str, data_str + size, &root, nullptr);
} catch (Json::Exception const&) { } catch (Json::Exception const&) {

View File

@@ -267,7 +267,7 @@ bool Runner::runAllTest(bool printSummary) const {
printf("All %zu tests passed\n", count); printf("All %zu tests passed\n", count);
} }
return true; return true;
} else { }
for (auto& result : failures) { for (auto& result : failures) {
result.printFailure(count > 1); result.printFailure(count > 1);
} }
@@ -279,7 +279,6 @@ bool Runner::runAllTest(bool printSummary) const {
failedCount); failedCount);
} }
return false; return false;
}
} }
bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const { bool Runner::testIndex(const Json::String& testName, size_t& indexOut) const {
@@ -308,7 +307,8 @@ int Runner::runCommandLine(int argc, const char* argv[]) const {
if (opt == "--list-tests") { if (opt == "--list-tests") {
listTests(); listTests();
return 0; return 0;
} else if (opt == "--test-auto") { }
if (opt == "--test-auto") {
preventDialogOnCrash(); preventDialogOnCrash();
} else if (opt == "--test") { } else if (opt == "--test") {
++index; ++index;

View File

@@ -42,7 +42,7 @@ public:
/// Must be a POD to allow inline initialisation without stepping /// Must be a POD to allow inline initialisation without stepping
/// into the debugger. /// into the debugger.
struct PredicateContext { struct PredicateContext {
typedef unsigned int Id; using Id = unsigned int;
Id id_; Id id_;
const char* file_; const char* file_;
unsigned int line_; unsigned int line_;
@@ -102,7 +102,7 @@ private:
static Json::String indentText(const Json::String& text, static Json::String indentText(const Json::String& text,
const Json::String& indent); const Json::String& indent);
typedef std::deque<Failure> Failures; using Failures = std::deque<Failure>;
Failures failures_; Failures failures_;
Json::String name_; Json::String name_;
PredicateContext rootPredicateNode_; PredicateContext rootPredicateNode_;
@@ -129,7 +129,7 @@ private:
}; };
/// Function pointer type for TestCase factory /// Function pointer type for TestCase factory
typedef TestCase* (*TestCaseFactory)(); using TestCaseFactory = TestCase* (*)();
class Runner { class Runner {
public: public:
@@ -168,7 +168,7 @@ private:
static void preventDialogOnCrash(); static void preventDialogOnCrash();
private: private:
typedef std::deque<TestCaseFactory> Factories; using Factories = std::deque<TestCaseFactory>;
Factories tests_; Factories tests_;
}; };
@@ -207,7 +207,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
/// The predicate may do other assertions and be a member function of the /// The predicate may do other assertions and be a member function of the
/// fixture. /// fixture.
#define JSONTEST_ASSERT_PRED(expr) \ #define JSONTEST_ASSERT_PRED(expr) \
{ \ do { \
JsonTest::PredicateContext _minitest_Context = { \ JsonTest::PredicateContext _minitest_Context = { \
result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \ result_->predicateId_, __FILE__, __LINE__, #expr, NULL, NULL}; \
result_->predicateStackTail_->next_ = &_minitest_Context; \ result_->predicateStackTail_->next_ = &_minitest_Context; \
@@ -215,7 +215,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
result_->predicateStackTail_ = &_minitest_Context; \ result_->predicateStackTail_ = &_minitest_Context; \
(expr); \ (expr); \
result_->popPredicateContext(); \ result_->popPredicateContext(); \
} } while (0)
/// \brief Asserts that two values are equals. /// \brief Asserts that two values are equals.
#define JSONTEST_ASSERT_EQUAL(expected, actual) \ #define JSONTEST_ASSERT_EQUAL(expected, actual) \
@@ -230,7 +230,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
/// \brief Asserts that a given expression throws an exception /// \brief Asserts that a given expression throws an exception
#define JSONTEST_ASSERT_THROWS(expr) \ #define JSONTEST_ASSERT_THROWS(expr) \
{ \ do { \
bool _threw = false; \ bool _threw = false; \
try { \ try { \
expr; \ expr; \
@@ -240,7 +240,7 @@ TestResult& checkStringEqual(TestResult& result, const Json::String& expected,
if (!_threw) \ if (!_threw) \
result_->addFailure(__FILE__, __LINE__, \ result_->addFailure(__FILE__, __LINE__, \
"expected exception thrown: " #expr); \ "expected exception thrown: " #expr); \
} } while (0)
/// \brief Begin a fixture test case. /// \brief Begin a fixture test case.
#define JSONTEST_FIXTURE(FixtureType, name) \ #define JSONTEST_FIXTURE(FixtureType, name) \

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1 @@
{'//this is bad JSON.'}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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