Merge branch 'develop' into doctest

pull/1439/head
Viktor Kirilov 2019-03-18 16:59:36 +02:00 committed by GitHub
commit 365944b0bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
60 changed files with 15683 additions and 7958 deletions

23
.clang-tidy 100644
View File

@ -0,0 +1,23 @@
Checks: '-*,
bugprone-*,
cert-*,
clang-analyzer-*,
google-*,
-google-runtime-references,
hicpp-*,
-hicpp-no-array-decay,
-hicpp-uppercase-literal-suffix,
misc-*,
-misc-non-private-member-variables-in-classes,
llvm-*,
-llvm-header-guard,
modernize-*,
performance-*,
portability-*,
readability-*,
-readability-magic-numbers,
-readability-uppercase-literal-suffix'
CheckOptions:
- key: hicpp-special-member-functions.AllowSoleDefaultDtor
value: 1

View File

@ -128,21 +128,6 @@ matrix:
# OSX / Clang
- os: osx
osx_image: xcode6.4
- os: osx
osx_image: xcode7.3
- os: osx
osx_image: xcode8
- os: osx
osx_image: xcode8.1
- os: osx
osx_image: xcode8.2
- os: osx
osx_image: xcode8.3
@ -164,6 +149,9 @@ matrix:
- os: osx
osx_image: xcode10
- os: osx
osx_image: xcode10.1
# Linux / GCC
- os: linux
@ -290,15 +278,23 @@ matrix:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
- os: linux
compiler: clang
env: COMPILER=clang++-7
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
packages: ['g++-6', 'clang-7', 'ninja-build']
- os: linux
compiler: clang
env:
- COMPILER=clang++-6.0
- COMPILER=clang++-7
- CXXFLAGS=-std=c++1z
addons:
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
packages: ['g++-6', 'clang-6.0', 'ninja-build']
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
packages: ['g++-6', 'clang-7', 'ninja-build']
################
# build script #

View File

@ -16,6 +16,7 @@ include(ExternalProject)
## OPTIONS
##
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
option(JSON_Install "Install CMake targets during install step." ON)
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
##
@ -46,7 +47,11 @@ endif()
##
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_range_for)
else()
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
endif()
target_include_directories(
${NLOHMANN_JSON_TARGET_NAME}
@ -92,32 +97,34 @@ configure_file(
@ONLY
)
install(
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
)
install(
FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)
if (NLOHMANN_ADD_NATVIS)
if(JSON_Install)
install(
FILES ${NLOHMANN_NATVIS_FILE}
DESTINATION .
)
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
)
install(
FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)
if (NLOHMANN_ADD_NATVIS)
install(
FILES ${NLOHMANN_NATVIS_FILE}
DESTINATION .
)
endif()
export(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
)
install(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
)
install(
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)
endif()
export(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
NAMESPACE ${PROJECT_NAME}::
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
)
install(
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
)
install(
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
NAMESPACE ${PROJECT_NAME}::
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
)

214
Makefile
View File

@ -49,6 +49,9 @@ all:
@echo "clean - remove built files"
@echo "coverage - create coverage information with lcov"
@echo "cppcheck - analyze code with cppcheck"
@echo "cpplint - analyze code with cpplint"
@echo "clang_tidy - analyze code with Clang-Tidy"
@echo "clang_analyze - analyze code with Clang-Analyzer"
@echo "doctest - compile example files and check their output"
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
@ -122,7 +125,7 @@ doctest:
# -Wno-c++2a-compat: u8 literals will behave differently in C++20...
# -Wno-padded: padding is nothing to warn about
pedantic_clang:
$(MAKE) json_unit CXX=$(COMPILER_DIR)/clang++ CXXFLAGS="\
$(MAKE) json_unit CXX=$(COMPILER_DIR)/clang++ CXXFLAGS=" \
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
-Werror \
-Weverything \
@ -134,72 +137,233 @@ pedantic_clang:
-Wno-float-equal \
-Wno-switch-enum -Wno-covered-switch-default \
-Wno-c++2a-compat \
-Wno-c++17-extensions \
-Wno-padded"
# calling GCC with most warnings
pedantic_gcc:
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS="\
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS=" \
-std=c++11 \
-Wno-deprecated-declarations \
-Werror \
-Wall -Wpedantic -Wextra \
-Waddress \
-Waddress-of-packed-member \
-Waggressive-loop-optimizations \
-Waligned-new=all \
-Wall \
-Walloc-zero \
-Walloca \
-Warray-bounds \
-Warray-bounds=2 \
-Wcast-qual -Wcast-align \
-Wattribute-alias=2 \
-Wattribute-warning \
-Wattributes \
-Wbool-compare \
-Wbool-operation \
-Wbuiltin-declaration-mismatch \
-Wbuiltin-macro-redefined \
-Wcannot-profile \
-Wcast-align \
-Wcast-function-type \
-Wcast-qual \
-Wcatch-value=3 \
-Wchar-subscripts \
-Wclass-conversion \
-Wclass-memaccess \
-Wclobbered \
-Wcomment \
-Wcomments \
-Wconditionally-supported \
-Wconversion \
-Wconversion-null \
-Wcoverage-mismatch \
-Wcpp \
-Wctor-dtor-privacy \
-Wdangling-else \
-Wdate-time \
-Wdelete-incomplete \
-Wdelete-non-virtual-dtor \
-Wdeprecated \
-Wdeprecated-copy \
-Wdeprecated-copy-dtor \
-Wdeprecated-declarations \
-Wdisabled-optimization \
-Wdiv-by-zero \
-Wdouble-promotion \
-Wduplicated-branches \
-Wduplicated-cond \
-Weffc++ \
-Wempty-body \
-Wendif-labels \
-Wenum-compare \
-Wexpansion-to-defined \
-Werror \
-Wextra \
-Wextra-semi \
-Wfloat-conversion \
-Wfloat-equal \
-Wformat \
-Wformat-contains-nul \
-Wformat-extra-args \
-Wformat-nonliteral \
-Wformat-overflow=2 \
-Wformat-security \
-Wformat-signedness \
-Wformat-truncation=2 \
-Wformat-y2k \
-Wformat-zero-length \
-Wformat=2 \
-Wno-ignored-qualifiers \
-Wframe-address \
-Wfree-nonheap-object \
-Whsa \
-Wif-not-aligned \
-Wignored-attributes \
-Wignored-qualifiers \
-Wimplicit-fallthrough=5 \
-Winherited-variadic-ctor \
-Winit-list-lifetime \
-Winit-self \
-Winline \
-Wint-in-bool-context \
-Wint-to-pointer-cast \
-Winvalid-memory-model \
-Winvalid-offsetof \
-Winvalid-pch \
-Wliteral-suffix \
-Wlogical-not-parentheses \
-Wlogical-op \
-Wlto-type-mismatch \
-Wmain \
-Wmaybe-uninitialized \
-Wmemset-elt-size \
-Wmemset-transposed-args \
-Wmisleading-indentation \
-Wmissing-attributes \
-Wmissing-braces \
-Wmissing-declarations \
-Wmissing-field-initializers \
-Wmissing-format-attribute \
-Wmissing-include-dirs \
-Wmissing-noreturn \
-Wmissing-profile \
-Wmultichar \
-Wmultiple-inheritance \
-Wmultistatement-macros \
-Wnarrowing \
-Wno-deprecated-declarations \
-Wno-long-long \
-Wno-namespaces \
-Wno-padded \
-Wno-switch-enum \
-Wno-system-headers \
-Wno-templates \
-Wno-undef \
-Wnoexcept \
-Wnoexcept-type \
-Wnon-template-friend \
-Wnon-virtual-dtor \
-Wnonnull \
-Wnonnull-compare \
-Wnonportable-cfstrings \
-Wnormalized \
-Wnull-dereference \
-Wodr \
-Wold-style-cast \
-Wopenmp-simd \
-Woverflow \
-Woverlength-strings \
-Woverloaded-virtual \
-Wpacked \
-Wpacked-bitfield-compat \
-Wpacked-not-aligned \
-Wparentheses \
-Wpedantic \
-Wpessimizing-move \
-Wplacement-new=2 \
-Wpmf-conversions \
-Wpointer-arith \
-Wpointer-compare \
-Wpragmas \
-Wprio-ctor-dtor \
-Wpsabi \
-Wredundant-decls \
-Wredundant-move \
-Wregister \
-Wreorder \
-Wrestrict \
-Wreturn-local-addr \
-Wreturn-type \
-Wscalar-storage-order \
-Wsequence-point \
-Wshadow \
-Wshadow-compatible-local \
-Wshadow-local \
-Wshadow=compatible-local \
-Wshadow=global \
-Wshadow=local \
-Wshift-count-negative \
-Wshift-count-overflow \
-Wshift-negative-value \
-Wshift-overflow=2 \
-Wsign-compare \
-Wsign-conversion \
-Wsign-promo \
-Wsized-deallocation \
-Wsizeof-array-argument \
-Wsizeof-pointer-div \
-Wsizeof-pointer-memaccess \
-Wstack-protector \
-Wstrict-aliasing=3 \
-Wstrict-null-sentinel \
-Wstrict-overflow=5 \
-Wstringop-overflow=4 \
-Wstringop-truncation \
-Wsubobject-linkage \
-Wsuggest-attribute=cold \
-Wsuggest-attribute=const \
-Wsuggest-attribute=format \
-Wsuggest-attribute=malloc \
-Wsuggest-attribute=noreturn \
-Wsuggest-attribute=pure \
-Wsuggest-final-methods \
-Wsuggest-final-types \
-Wsuggest-override \
-Wswitch \
-Wswitch-bool \
-Wswitch-default \
-Wswitch-unreachable \
-Wsync-nand \
-Wsynth \
-Wtautological-compare \
-Wterminate \
-Wtrampolines \
-Wtrigraphs \
-Wundef \
-Wuninitialized -Wunknown-pragmas \
-Wtype-limits \
-Wuninitialized \
-Wunknown-pragmas \
-Wunreachable-code \
-Wunsafe-loop-optimizations \
-Wunused \
-Wunused-but-set-parameter \
-Wunused-but-set-variable \
-Wunused-const-variable=2 \
-Wunused-function \
-Wunused-label \
-Wunused-local-typedefs \
-Wunused-macros \
-Wunused-parameter \
-Wunused-result \
-Wunused-value \
-Wunused-variable \
-Wuseless-cast \
-Wvarargs \
-Wvariadic-macros \
-Wctor-dtor-privacy \
-Winit-self \
-Wstrict-null-sentinel"
-Wvector-operation-performance \
-Wvirtual-inheritance \
-Wvirtual-move-assign \
-Wvla \
-Wvolatile-register-var \
-Wwrite-strings \
-Wzero-as-null-pointer-constant \
"
##########################################################################
# benchmarks
@ -276,7 +440,7 @@ fuzzing-stop:
# call cppcheck on the main header file
cppcheck:
cppcheck --enable=warning --inconclusive --force --std=c++11 $(AMALGAMATED_FILE) --error-exitcode=1
cppcheck --enable=warning --inconclusive --force --std=c++11 $(SRCS) --error-exitcode=1
# compile and check with Clang Static Analyzer
clang_analyze:
@ -285,6 +449,30 @@ clang_analyze:
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja
cd clang_analyze_build ; $(COMPILER_DIR)/scan-build -enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull --use-c++=$(COMPILER_DIR)/clang++ --view -analyze-headers -o clang_analyze_build/report.html ninja
# call cpplint (some errors expected due to false positives)
cpplint:
third_party/cpplint/cpplint.py --filter=-whitespace,-legal,-readability/alt_tokens,-runtime/references,-runtime/explicit --quiet --recursive include
clang_tidy:
$(COMPILER_DIR)/clang-tidy $(SRCS) -- -Iinclude -std=c++11
pvs_studio:
rm -fr pvs_studio_build
mkdir pvs_studio_build
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On
cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10
cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
open pvs_studio_build/pvs/index.html
infer:
rm -fr infer_build
mkdir infer_build
cd infer_build ; infer compile -- cmake .. ; infer run -- make -j 4
oclint:
oclint $(SRCS) -report-type html -enable-global-analysis -o oclint_report.html -max-priority-1=10000 -max-priority-2=10000 -max-priority-3=10000 -- -std=c++11 -Iinclude
open oclint_report.html
##########################################################################
# maintainer targets
##########################################################################

View File

@ -100,6 +100,10 @@ To embed the library directly into an existing CMake project, place the entire s
# run from your own project's code.
set(JSON_BuildTests OFF CACHE INTERNAL "")
# If you only include this third party in PRIVATE source files, you do not
# need to install it when your main project gets installed.
# set(JSON_Install OFF CACHE INTERNAL "")
# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it
# unintended consequences that will break the build. It's generally
# discouraged (although not necessarily well documented as such) to use
@ -155,7 +159,7 @@ If you are using [Spack](https://www.spack.io/) to manage your dependencies, you
If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json).
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. Please file issues [here](https://github.com/buckaroo-pm/nlohmann-json). There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example).
If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json). Please see the vcpkg project for any issues regarding the packaging.
@ -165,6 +169,8 @@ If you are using [CocoaPods](https://cocoapods.org), you can use the library by
If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/). Please check [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) on how to use the package. Please files issues [here](https://github.com/hnkb/nlohmann-json-nuget/issues).
If you are using [conda](https://conda.io/), you can use the package [nlohmann_json](https://github.com/conda-forge/nlohmann_json-feedstock) from [conda-forge](https://conda-forge.org) executing `conda install -c conda-forge nlohmann_json`. Please file issues [here](https://github.com/conda-forge/nlohmann_json-feedstock/issues).
## Examples
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
@ -615,7 +621,7 @@ json j_patch = R"({
})"_json;
// apply the patch
j_original.merge_patch(j_patch);
j_document.merge_patch(j_patch);
// {
// "a": "z",
// "c": {
@ -747,7 +753,7 @@ Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_jso
Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
@ -915,7 +921,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, {
{TS_STOPPED, "stopped"},
{TS_RUNNING, "running"},
{TS_COMPLETED, "completed"},
});
})
```
The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serilization code.
@ -1034,17 +1040,14 @@ The following compilers are currently used in continuous integration at [Travis]
| Clang 4.0.1 | Ubuntu 14.04.1 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
| Clang 5.0.2 | Ubuntu 14.04.1 LTS | clang version 5.0.2-svn328729-1~exp1~20180509123505.100 (branches/release_50) |
| Clang 6.0.1 | Ubuntu 14.04.1 LTS | clang version 6.0.1-svn334776-1~exp1~20180726133705.85 (branches/release_60) |
| Clang Xcode 6.4 | OSX 10.10.5 | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
| Clang Xcode 7.3 | OSX 10.11.6 | Apple LLVM version 7.3.0 (clang-703.0.31) |
| Clang Xcode 8.0 | OSX 10.11.6 | Apple LLVM version 8.0.0 (clang-800.0.38) |
| Clang Xcode 8.1 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang Xcode 8.2 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
| Clang 7.0.1 | Ubuntu 14.04.1 LTS | clang version 7.0.1-svn348686-1~exp1~20181213084532.54 (branches/release_70) |
| Clang Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) |
| Clang Xcode 9.0 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.37) |
| Clang Xcode 9.1 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.38) |
| Clang Xcode 9.2 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.1) |
| Clang Xcode 9.3 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.2) |
| Clang Xcode 10.0 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.2) |
| Clang Xcode 10.1 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.5) |
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 |
| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 |

View File

@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.1)
cmake_minimum_required(VERSION 3.8)
project(JSON_Benchmarks LANGUAGES CXX)
# set compiler flags

View File

@ -1,4 +1,4 @@
# Doxyfile 1.8.15
# Doxyfile 1.8.16
#---------------------------------------------------------------------------
# Project related configuration options
@ -38,6 +38,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
OPTIMIZE_OUTPUT_SLICE = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
TOC_INCLUDE_HEADINGS = 0
@ -141,7 +142,7 @@ USE_HTAGS = NO
VERBATIM_HEADERS = NO
CLANG_ASSISTED_PARSING = YES
CLANG_OPTIONS = -std=c++11
CLANG_COMPILATION_DATABASE_PATH = 0
CLANG_DATABASE_PATH =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
@ -214,6 +215,7 @@ GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
LATEX_MAKEINDEX_CMD = \makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
@ -228,6 +230,7 @@ LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
LATEX_EMOJI_DIRECTORY =
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
@ -252,6 +255,7 @@ MAN_LINKS = NO
GENERATE_XML = YES
XML_OUTPUT = xml
XML_PROGRAMLISTING = YES
XML_NS_MEMB_FILE_SCOPE = NO
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------

View File

@ -0,0 +1,17 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create some JSON values
json j_object = R"( {"key": "value"} )"_json;
json j_array = R"( [1, 2, 3] )"_json;
// call contains
std::cout << std::boolalpha <<
"j_object contains 'key': " << j_object.contains("key") << '\n' <<
"j_object contains 'another': " << j_object.contains("another") << '\n' <<
"j_array contains 'key': " << j_array.contains("key") << std::endl;
}

View File

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/iHSlXjtjhgO9Q1Tw"><b>online</b></a>

View File

@ -0,0 +1,3 @@
j_object contains 'key': true
j_object contains 'another': false
j_array contains 'key': false

View File

@ -0,0 +1,20 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// different JSON Pointers
json::json_pointer ptr0;
json::json_pointer ptr1("");
json::json_pointer ptr2("/foo");
json::json_pointer ptr3("/foo/0");
// call empty()
std::cout << std::boolalpha
<< ptr0 << ": " << ptr0.empty() << '\n'
<< ptr1 << ": " << ptr1.empty() << '\n'
<< ptr2 << ": " << ptr2.empty() << '\n'
<< ptr3 << ": " << ptr3.empty() << std::endl;
}

View File

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/pqG2Q8bmj9SvSX0i"><b>online</b></a>

View File

@ -0,0 +1,4 @@
"": true
"": true
"/foo": false
"/foo/0": false

View File

@ -0,0 +1,18 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// different JSON Pointers
json::json_pointer ptr1("");
json::json_pointer ptr2("/foo");
json::json_pointer ptr3("/foo/0");
// call parent_pointer()
std::cout << std::boolalpha
<< "parent of " << ptr1 << " is " << ptr1.parent_pointer() << '\n'
<< "parent of " << ptr2 << " is " << ptr2.parent_pointer() << '\n'
<< "parent of " << ptr3 << " is " << ptr3.parent_pointer() << std::endl;
}

View File

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/yweqBQ8bAC6pcn68"><b>online</b></a>

View File

@ -0,0 +1,3 @@
parent of "" is ""
parent of "/foo" is ""
parent of "/foo/0" is "/foo"

View File

@ -0,0 +1,21 @@
#include <iostream>
#include <nlohmann/json.hpp>
using json = nlohmann::json;
int main()
{
// create empty JSON Pointer
json::json_pointer ptr;
std::cout << ptr << '\n';
// call push_back()
ptr.push_back("foo");
std::cout << ptr << '\n';
ptr.push_back("0");
std::cout << ptr << '\n';
ptr.push_back("bar");
std::cout << ptr << '\n';
}

View File

@ -0,0 +1 @@
<a target="_blank" href="https://wandbox.org/permlink/kLC7IUvqQ6XJCeG9"><b>online</b></a>

View File

@ -0,0 +1,4 @@
""
"/foo"
"/foo/0"
"/foo/0/bar"

View File

@ -57,6 +57,7 @@ These pages contain the API documentation of JSON for Modern C++, a C++11 header
- @link nlohmann::basic_json::number_integer_t signed integers @endlink
- @link nlohmann::basic_json::number_unsigned_t unsigned integers @endlink
- @link nlohmann::basic_json::number_float_t floating-point @endlink
- @link nlohmann::json_pointer JSON Pointer @endlink
# Container function overview

View File

@ -1,5 +1,6 @@
#pragma once
#include <array> // array
#include <cassert> // assert
#include <ciso646> // or, and, not
#include <cmath> // signbit, isfinite
@ -49,10 +50,10 @@ struct diyfp // f * 2^e
{
static constexpr int kPrecision = 64; // = q
uint64_t f = 0;
std::uint64_t f = 0;
int e = 0;
constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
/*!
@brief returns x - y
@ -97,23 +98,23 @@ struct diyfp // f * 2^e
//
// = p_lo + 2^64 p_hi
const uint64_t u_lo = x.f & 0xFFFFFFFF;
const uint64_t u_hi = x.f >> 32;
const uint64_t v_lo = y.f & 0xFFFFFFFF;
const uint64_t v_hi = y.f >> 32;
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
const std::uint64_t u_hi = x.f >> 32u;
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
const std::uint64_t v_hi = y.f >> 32u;
const uint64_t p0 = u_lo * v_lo;
const uint64_t p1 = u_lo * v_hi;
const uint64_t p2 = u_hi * v_lo;
const uint64_t p3 = u_hi * v_hi;
const std::uint64_t p0 = u_lo * v_lo;
const std::uint64_t p1 = u_lo * v_hi;
const std::uint64_t p2 = u_hi * v_lo;
const std::uint64_t p3 = u_hi * v_hi;
const uint64_t p0_hi = p0 >> 32;
const uint64_t p1_lo = p1 & 0xFFFFFFFF;
const uint64_t p1_hi = p1 >> 32;
const uint64_t p2_lo = p2 & 0xFFFFFFFF;
const uint64_t p2_hi = p2 >> 32;
const std::uint64_t p0_hi = p0 >> 32u;
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
const std::uint64_t p1_hi = p1 >> 32u;
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
const std::uint64_t p2_hi = p2 >> 32u;
uint64_t Q = p0_hi + p1_lo + p2_lo;
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
// The full product might now be computed as
//
@ -124,9 +125,9 @@ struct diyfp // f * 2^e
// Effectively we only need to add the highest bit in p_lo to p_hi (and
// Q_hi + 1 does not overflow).
Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
return {h, x.e + y.e + 64};
}
@ -139,9 +140,9 @@ struct diyfp // f * 2^e
{
assert(x.f != 0);
while ((x.f >> 63) == 0)
while ((x.f >> 63u) == 0)
{
x.f <<= 1;
x.f <<= 1u;
x.e--;
}
@ -195,15 +196,15 @@ boundaries compute_boundaries(FloatType value)
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
constexpr int kMinExp = 1 - kBias;
constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
const uint64_t bits = reinterpret_bits<bits_type>(value);
const uint64_t E = bits >> (kPrecision - 1);
const uint64_t F = bits & (kHiddenBit - 1);
const std::uint64_t bits = reinterpret_bits<bits_type>(value);
const std::uint64_t E = bits >> (kPrecision - 1);
const std::uint64_t F = bits & (kHiddenBit - 1);
const bool is_denormal = (E == 0);
const bool is_denormal = E == 0;
const diyfp v = is_denormal
? diyfp(F, kMinExp)
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
@ -229,7 +230,7 @@ boundaries compute_boundaries(FloatType value)
// -----------------+------+------+-------------+-------------+--- (B)
// v- m- v m+ v+
const bool lower_boundary_is_closer = (F == 0 and E > 1);
const bool lower_boundary_is_closer = F == 0 and E > 1;
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
const diyfp m_minus = lower_boundary_is_closer
? diyfp(4 * v.f - 1, v.e - 2) // (B)
@ -304,7 +305,7 @@ constexpr int kGamma = -32;
struct cached_power // c = f * 2^e ~= 10^k
{
uint64_t f;
std::uint64_t f;
int e;
int k;
};
@ -368,91 +369,92 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
// NB:
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
constexpr int kCachedPowersSize = 79;
constexpr int kCachedPowersMinDecExp = -300;
constexpr int kCachedPowersDecStep = 8;
static constexpr cached_power kCachedPowers[] =
static constexpr std::array<cached_power, 79> kCachedPowers =
{
{ 0xAB70FE17C79AC6CA, -1060, -300 },
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
{ 0xBE5691EF416BD60C, -1007, -284 },
{ 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 },
{ 0x9D71AC8FADA6C9B5, -927, -260 },
{ 0xEA9C227723EE8BCB, -901, -252 },
{ 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 },
{ 0xC21094364DFB5637, -821, -228 },
{ 0x9096EA6F3848984F, -794, -220 },
{ 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 },
{ 0xEF340A98172AACE5, -715, -196 },
{ 0xB23867FB2A35B28E, -688, -188 },
{ 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 },
{ 0x936B9FCEBB25C996, -608, -164 },
{ 0xDBAC6C247D62A584, -582, -156 },
{ 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 },
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
{ 0x87625F056C7C4A8B, -475, -124 },
{ 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 },
{ 0xDFF9772470297EBD, -396, -100 },
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
{ 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 },
{ 0x8A08F0F8BF0F156B, -289, -68 },
{ 0xCDB02555653131B6, -263, -60 },
{ 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 },
{ 0xAA242499697392D3, -183, -36 },
{ 0xFD87B5F28300CA0E, -157, -28 },
{ 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 },
{ 0xD1B71758E219652C, -77, -4 },
{ 0x9C40000000000000, -50, 4 },
{ 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 },
{ 0x813F3978F8940984, 30, 28 },
{ 0xC097CE7BC90715B3, 56, 36 },
{ 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 },
{ 0x9F4F2726179A2245, 136, 60 },
{ 0xED63A231D4C4FB27, 162, 68 },
{ 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 },
{ 0xC45D1DF942711D9A, 242, 92 },
{ 0x924D692CA61BE758, 269, 100 },
{ 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 },
{ 0xF209787BB47D6B85, 348, 124 },
{ 0xB454E4A179DD1877, 375, 132 },
{ 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 },
{ 0x952AB45CFA97A0B3, 455, 156 },
{ 0xDE469FBD99A05FE3, 481, 164 },
{ 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 },
{ 0xB7DCBF5354E9BECE, 561, 188 },
{ 0x88FCF317F22241E2, 588, 196 },
{ 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 },
{ 0xE2A0B5DC971F303A, 667, 220 },
{ 0xA8D9D1535CE3B396, 694, 228 },
{ 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 },
{ 0x8BAB8EEFB6409C1A, 774, 252 },
{ 0xD01FEF10A657842C, 800, 260 },
{ 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 },
{ 0xAC2820D9623BF429, 880, 284 },
{ 0x80444B5E7AA7CF85, 907, 292 },
{ 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 },
{ 0xD433179D9C8CB841, 986, 316 },
{ 0x9E19DB92B4E31BA9, 1013, 324 },
{
{ 0xAB70FE17C79AC6CA, -1060, -300 },
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
{ 0xBE5691EF416BD60C, -1007, -284 },
{ 0x8DD01FAD907FFC3C, -980, -276 },
{ 0xD3515C2831559A83, -954, -268 },
{ 0x9D71AC8FADA6C9B5, -927, -260 },
{ 0xEA9C227723EE8BCB, -901, -252 },
{ 0xAECC49914078536D, -874, -244 },
{ 0x823C12795DB6CE57, -847, -236 },
{ 0xC21094364DFB5637, -821, -228 },
{ 0x9096EA6F3848984F, -794, -220 },
{ 0xD77485CB25823AC7, -768, -212 },
{ 0xA086CFCD97BF97F4, -741, -204 },
{ 0xEF340A98172AACE5, -715, -196 },
{ 0xB23867FB2A35B28E, -688, -188 },
{ 0x84C8D4DFD2C63F3B, -661, -180 },
{ 0xC5DD44271AD3CDBA, -635, -172 },
{ 0x936B9FCEBB25C996, -608, -164 },
{ 0xDBAC6C247D62A584, -582, -156 },
{ 0xA3AB66580D5FDAF6, -555, -148 },
{ 0xF3E2F893DEC3F126, -529, -140 },
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
{ 0x87625F056C7C4A8B, -475, -124 },
{ 0xC9BCFF6034C13053, -449, -116 },
{ 0x964E858C91BA2655, -422, -108 },
{ 0xDFF9772470297EBD, -396, -100 },
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
{ 0xF8A95FCF88747D94, -343, -84 },
{ 0xB94470938FA89BCF, -316, -76 },
{ 0x8A08F0F8BF0F156B, -289, -68 },
{ 0xCDB02555653131B6, -263, -60 },
{ 0x993FE2C6D07B7FAC, -236, -52 },
{ 0xE45C10C42A2B3B06, -210, -44 },
{ 0xAA242499697392D3, -183, -36 },
{ 0xFD87B5F28300CA0E, -157, -28 },
{ 0xBCE5086492111AEB, -130, -20 },
{ 0x8CBCCC096F5088CC, -103, -12 },
{ 0xD1B71758E219652C, -77, -4 },
{ 0x9C40000000000000, -50, 4 },
{ 0xE8D4A51000000000, -24, 12 },
{ 0xAD78EBC5AC620000, 3, 20 },
{ 0x813F3978F8940984, 30, 28 },
{ 0xC097CE7BC90715B3, 56, 36 },
{ 0x8F7E32CE7BEA5C70, 83, 44 },
{ 0xD5D238A4ABE98068, 109, 52 },
{ 0x9F4F2726179A2245, 136, 60 },
{ 0xED63A231D4C4FB27, 162, 68 },
{ 0xB0DE65388CC8ADA8, 189, 76 },
{ 0x83C7088E1AAB65DB, 216, 84 },
{ 0xC45D1DF942711D9A, 242, 92 },
{ 0x924D692CA61BE758, 269, 100 },
{ 0xDA01EE641A708DEA, 295, 108 },
{ 0xA26DA3999AEF774A, 322, 116 },
{ 0xF209787BB47D6B85, 348, 124 },
{ 0xB454E4A179DD1877, 375, 132 },
{ 0x865B86925B9BC5C2, 402, 140 },
{ 0xC83553C5C8965D3D, 428, 148 },
{ 0x952AB45CFA97A0B3, 455, 156 },
{ 0xDE469FBD99A05FE3, 481, 164 },
{ 0xA59BC234DB398C25, 508, 172 },
{ 0xF6C69A72A3989F5C, 534, 180 },
{ 0xB7DCBF5354E9BECE, 561, 188 },
{ 0x88FCF317F22241E2, 588, 196 },
{ 0xCC20CE9BD35C78A5, 614, 204 },
{ 0x98165AF37B2153DF, 641, 212 },
{ 0xE2A0B5DC971F303A, 667, 220 },
{ 0xA8D9D1535CE3B396, 694, 228 },
{ 0xFB9B7CD9A4A7443C, 720, 236 },
{ 0xBB764C4CA7A44410, 747, 244 },
{ 0x8BAB8EEFB6409C1A, 774, 252 },
{ 0xD01FEF10A657842C, 800, 260 },
{ 0x9B10A4E5E9913129, 827, 268 },
{ 0xE7109BFBA19C0C9D, 853, 276 },
{ 0xAC2820D9623BF429, 880, 284 },
{ 0x80444B5E7AA7CF85, 907, 292 },
{ 0xBF21E44003ACDD2D, 933, 300 },
{ 0x8E679C2F5E44FF8F, 960, 308 },
{ 0xD433179D9C8CB841, 986, 316 },
{ 0x9E19DB92B4E31BA9, 1013, 324 },
}
};
// This computation gives exactly the same results for k as
@ -466,10 +468,9 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
assert(index >= 0);
assert(index < kCachedPowersSize);
static_cast<void>(kCachedPowersSize); // Fix warning.
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
const cached_power cached = kCachedPowers[index];
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
assert(kAlpha <= cached.e + e + 64);
assert(kGamma >= cached.e + e + 64);
@ -480,7 +481,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
For n == 0, returns 1 and sets pow10 := 1.
*/
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
{
// LCOV_EXCL_START
if (n >= 1000000000)
@ -536,8 +537,8 @@ inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
}
}
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
uint64_t rest, uint64_t ten_k)
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
std::uint64_t rest, std::uint64_t ten_k)
{
assert(len >= 1);
assert(dist <= delta);
@ -598,8 +599,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
assert(M_plus.e >= kAlpha);
assert(M_plus.e <= kGamma);
uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
//
@ -608,10 +609,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// = ((p1 ) * 2^-e + (p2 )) * 2^e
// = p1 + p2 * 2^e
const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
// 1)
//
@ -619,7 +620,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
assert(p1 > 0);
uint32_t pow10;
std::uint32_t pow10;
const int k = find_largest_pow10(p1, pow10);
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
@ -647,8 +648,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
// pow10 = 10^(n-1) <= p1 < 10^n
//
const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
//
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
@ -673,7 +674,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// Note:
// Since rest and delta share the same exponent e, it suffices to
// compare the significands.
const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
if (rest <= delta)
{
// V = buffer * 10^n, with M- <= V <= M+.
@ -689,7 +690,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
//
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
//
const uint64_t ten_n = uint64_t{pow10} << -one.e;
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
grisu2_round(buffer, length, dist, delta, rest, ten_n);
return;
@ -751,10 +752,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
//
assert(p2 <= UINT64_MAX / 10);
assert(p2 <= std::numeric_limits<std::uint64_t>::max() / 10);
p2 *= 10;
const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
//
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
@ -794,7 +795,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
//
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
//
const uint64_t ten_m = one.f;
const std::uint64_t ten_m = one.f;
grisu2_round(buffer, length, dist, delta, p2, ten_m);
// By construction this algorithm generates the shortest possible decimal
@ -929,7 +930,7 @@ inline char* append_exponent(char* buf, int e)
*buf++ = '+';
}
auto k = static_cast<uint32_t>(e);
auto k = static_cast<std::uint32_t>(e);
if (k < 10)
{
// Always print at least two digits in the exponent.

View File

@ -1,17 +1,19 @@
#pragma once
#include <algorithm> // copy
#include <ciso646> // or, and, not
#include <iterator> // begin, end
#include <string> // string
#include <tuple> // tuple, get
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
#include <utility> // move, forward, declval, pair
#include <valarray> // valarray
#include <vector> // vector
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
namespace nlohmann
{

View File

@ -102,12 +102,12 @@ json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F
@liveexample{The following code shows how a `parse_error` exception can be
caught.,parse_error}
@sa @ref exception for the base class of the library exceptions
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -117,7 +117,7 @@ class parse_error : public exception
/*!
@brief create a parse error exception
@param[in] id_ the id of the exception
@param[in] position the position where the error occurred (or with
@param[in] pos the position where the error occurred (or with
chars_read_total=0 if the position cannot be
determined)
@param[in] what_arg the explanatory string
@ -188,12 +188,12 @@ json.exception.invalid_iterator.214 | cannot get value | Cannot get value for it
@liveexample{The following code shows how an `invalid_iterator` exception can be
caught.,invalid_iterator}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -223,7 +223,7 @@ name / id | example message | description
----------------------------- | --------------- | -------------------------
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
@ -242,11 +242,11 @@ json.exception.type_error.317 | JSON value cannot be serialized to requested for
@liveexample{The following code shows how a `type_error` exception can be
caught.,type_error}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -287,12 +287,12 @@ json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at
@liveexample{The following code shows how an `out_of_range` exception can be
caught.,out_of_range}
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref other_error for exceptions indicating other library errors
@sa - @ref other_error for exceptions indicating other library errors
@since version 3.0.0
*/
@ -321,12 +321,12 @@ name / id | example message | description
------------------------------ | --------------- | -------------------------
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
@sa @ref exception for the base class of the library exceptions
@sa @ref parse_error for exceptions indicating a parse error
@sa @ref invalid_iterator for exceptions indicating errors with iterators
@sa @ref type_error for exceptions indicating executing a member function with
@sa - @ref exception for the base class of the library exceptions
@sa - @ref parse_error for exceptions indicating a parse error
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
@sa - @ref type_error for exceptions indicating executing a member function with
a wrong type
@sa @ref out_of_range for exceptions indicating access out of the defined range
@sa - @ref out_of_range for exceptions indicating access out of the defined range
@liveexample{The following code shows how an `other_error` exception can be
caught.,other_error}

View File

@ -13,9 +13,9 @@
#include <string> // char_traits, string
#include <utility> // make_pair, move
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
@ -52,6 +52,13 @@ class binary_reader
assert(ia);
}
// make class move-only
binary_reader(const binary_reader&) = delete;
binary_reader(binary_reader&&) = default;
binary_reader& operator=(const binary_reader&) = delete;
binary_reader& operator=(binary_reader&&) = default;
~binary_reader() = default;
/*!
@param[in] format the binary format to parse
@param[in] sax_ a SAX event processor
@ -84,10 +91,8 @@ class binary_reader
result = parse_ubjson_internal();
break;
// LCOV_EXCL_START
default:
assert(false);
// LCOV_EXCL_STOP
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
// strict mode: next byte must be EOF
@ -121,7 +126,7 @@ class binary_reader
*/
static constexpr bool little_endianess(int num = 1) noexcept
{
return (*reinterpret_cast<char*>(&num) == 1);
return *reinterpret_cast<char*>(&num) == 1;
}
private:
@ -263,9 +268,9 @@ class binary_reader
default: // anything else not supported (yet)
{
char cr[3];
(std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr)));
std::array<char, 3> cr{};
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
}
}
}
@ -298,12 +303,9 @@ class binary_reader
return false;
}
if (not is_array)
if (not is_array and not sax->key(key))
{
if (not sax->key(key))
{
return false;
}
return false;
}
if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
@ -388,25 +390,25 @@ class binary_reader
case 0x18: // Unsigned integer (one-byte uint8_t follows)
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x19: // Unsigned integer (two-byte uint16_t follows)
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
}
@ -435,29 +437,29 @@ class binary_reader
case 0x35:
case 0x36:
case 0x37:
return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
case 0x38: // Negative integer (one-byte uint8_t follows)
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
}
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
- static_cast<number_integer_t>(number));
}
@ -522,29 +524,29 @@ class binary_reader
case 0x95:
case 0x96:
case 0x97:
return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
case 0x98: // array (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x99: // array (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9A: // array (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
case 0x9B: // array (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
}
@ -576,29 +578,29 @@ class binary_reader
case 0xB5:
case 0xB6:
case 0xB7:
return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
case 0xB8: // map (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xB9: // map (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBA: // map (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
case 0xBB: // map (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
}
@ -638,11 +640,11 @@ class binary_reader
// without such support. An example of a small decoder for
// half-precision floating-point numbers in the C language
// is shown in Fig. 3.
const int half = (byte1 << 8) + byte2;
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
const double val = [&half]
{
const int exp = (half >> 10) & 0x1F;
const int mant = half & 0x3FF;
const int exp = (half >> 10u) & 0x1Fu;
const unsigned int mant = half & 0x3FFu;
assert(0 <= exp and exp <= 32);
assert(0 <= mant and mant <= 1024);
switch (exp)
@ -657,7 +659,7 @@ class binary_reader
return std::ldexp(mant + 1024, exp - 25);
}
}();
return sax->number_float((half & 0x8000) != 0
return sax->number_float((half & 0x8000u) != 0
? static_cast<number_float_t>(-val)
: static_cast<number_float_t>(val), "");
}
@ -728,30 +730,30 @@ class binary_reader
case 0x76:
case 0x77:
{
return get_string(input_format_t::cbor, current & 0x1F, result);
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
}
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
{
uint64_t len;
std::uint64_t len;
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
}
@ -1026,7 +1028,7 @@ class binary_reader
case 0x8D:
case 0x8E:
case 0x8F:
return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixarray
case 0x90:
@ -1045,7 +1047,7 @@ class binary_reader
case 0x9D:
case 0x9E:
case 0x9F:
return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
// fixstr
case 0xA0:
@ -1108,49 +1110,49 @@ class binary_reader
case 0xCC: // uint 8
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCD: // uint 16
{
uint16_t number;
std::uint16_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCE: // uint 32
{
uint32_t number;
std::uint32_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xCF: // uint 64
{
uint64_t number;
std::uint64_t number;
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
}
case 0xD0: // int 8
{
int8_t number;
std::int8_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD1: // int 16
{
int16_t number;
std::int16_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD2: // int 32
{
int32_t number;
std::int32_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
case 0xD3: // int 64
{
int64_t number;
std::int64_t number;
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
}
@ -1164,25 +1166,25 @@ class binary_reader
case 0xDC: // array 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDD: // array 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
}
case 0xDE: // map 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
}
case 0xDF: // map 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
}
@ -1219,7 +1221,7 @@ class binary_reader
case 0xFD:
case 0xFE:
case 0xFF:
return sax->number_integer(static_cast<int8_t>(current));
return sax->number_integer(static_cast<std::int8_t>(current));
default: // anything else
{
@ -1282,24 +1284,24 @@ class binary_reader
case 0xBE:
case 0xBF:
{
return get_string(input_format_t::msgpack, current & 0x1F, result);
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
}
case 0xD9: // str 8
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
case 0xDA: // str 16
{
uint16_t len;
std::uint16_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
case 0xDB: // str 32
{
uint32_t len;
std::uint32_t len;
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
}
@ -1397,7 +1399,7 @@ class binary_reader
{
if (get_char)
{
get(); // TODO: may we ignore N here?
get(); // TODO(niels): may we ignore N here?
}
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
@ -1409,31 +1411,31 @@ class binary_reader
{
case 'U':
{
uint8_t len;
std::uint8_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'i':
{
int8_t len;
std::int8_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'I':
{
int16_t len;
std::int16_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'l':
{
int32_t len;
std::int32_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
case 'L':
{
int64_t len;
std::int64_t len;
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
}
@ -1453,7 +1455,7 @@ class binary_reader
{
case 'U':
{
uint8_t number;
std::uint8_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
@ -1464,7 +1466,7 @@ class binary_reader
case 'i':
{
int8_t number;
std::int8_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
@ -1475,7 +1477,7 @@ class binary_reader
case 'I':
{
int16_t number;
std::int16_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
@ -1486,7 +1488,7 @@ class binary_reader
case 'l':
{
int32_t number;
std::int32_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
@ -1497,7 +1499,7 @@ class binary_reader
case 'L':
{
int64_t number;
std::int64_t number;
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
{
return false;
@ -1552,10 +1554,12 @@ class binary_reader
return get_ubjson_size_value(result.first);
}
else if (current == '#')
if (current == '#')
{
return get_ubjson_size_value(result.first);
}
return true;
}
@ -1580,31 +1584,31 @@ class binary_reader
case 'U':
{
uint8_t number;
std::uint8_t number;
return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
}
case 'i':
{
int8_t number;
std::int8_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'I':
{
int16_t number;
std::int16_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'l':
{
int32_t number;
std::int32_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
case 'L':
{
int64_t number;
std::int64_t number;
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
}
@ -1809,7 +1813,7 @@ class binary_reader
int get()
{
++chars_read;
return (current = ia->get_character());
return current = ia->get_character();
}
/*!
@ -1843,7 +1847,7 @@ class binary_reader
bool get_number(const input_format_t format, NumberType& result)
{
// step 1: read input into array with system's byte order
std::array<uint8_t, sizeof(NumberType)> vec;
std::array<std::uint8_t, sizeof(NumberType)> vec;
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
{
get();
@ -1853,13 +1857,13 @@ class binary_reader
}
// reverse byte order prior to conversion if necessary
if (is_little_endian && !InputIsLittleEndian)
if (is_little_endian != InputIsLittleEndian)
{
vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
}
else
{
vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
}
}
@ -1920,9 +1924,9 @@ class binary_reader
*/
std::string get_token_string() const
{
char cr[3];
(std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
return std::string{cr};
std::array<char, 3> cr{};
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
return std::string{cr.data()};
}
/*!
@ -1955,10 +1959,8 @@ class binary_reader
error_msg += "BSON";
break;
// LCOV_EXCL_START
default:
assert(false);
// LCOV_EXCL_STOP
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
return error_msg + " " + context + ": " + detail;

View File

@ -1,7 +1,9 @@
#pragma once
#include <array> // array
#include <cassert> // assert
#include <cstddef> // size_t
#include <cstdio> //FILE *
#include <cstring> // strlen
#include <istream> // istream
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
@ -10,7 +12,6 @@
#include <string> // string, char_traits
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
#include <utility> // pair, declval
#include <cstdio> //FILE *
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@ -58,10 +59,18 @@ class file_input_adapter : public input_adapter_protocol
: m_file(f)
{}
// make class move-only
file_input_adapter(const file_input_adapter&) = delete;
file_input_adapter(file_input_adapter&&) = default;
file_input_adapter& operator=(const file_input_adapter&) = delete;
file_input_adapter& operator=(file_input_adapter&&) = default;
~file_input_adapter() override = default;
std::char_traits<char>::int_type get_character() noexcept override
{
return std::fgetc(m_file);
}
private:
/// the file pointer to read from
std::FILE* m_file;
@ -153,7 +162,11 @@ template<typename WideStringType, size_t T>
struct wide_string_input_helper
{
// UTF-32
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(const WideStringType& str,
size_t& current_wchar,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
@ -165,39 +178,39 @@ struct wide_string_input_helper
else
{
// get the current character
const auto wc = static_cast<int>(str[current_wchar++]);
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
// UTF-32 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
utf8_bytes_filled = 2;
}
else if (wc <= 0xFFFF)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
utf8_bytes_filled = 3;
}
else if (wc <= 0x10FFFF)
{
utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (wc & 0x3F);
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
utf8_bytes_filled = 4;
}
else
{
// unknown character
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
@ -208,7 +221,11 @@ template<typename WideStringType>
struct wide_string_input_helper<WideStringType, 2>
{
// UTF-16
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
static void fill_buffer(const WideStringType& str,
size_t& current_wchar,
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
size_t& utf8_bytes_index,
size_t& utf8_bytes_filled)
{
utf8_bytes_index = 0;
@ -220,44 +237,44 @@ struct wide_string_input_helper<WideStringType, 2>
else
{
// get the current character
const auto wc = static_cast<int>(str[current_wchar++]);
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
// UTF-16 to UTF-8 encoding
if (wc < 0x80)
{
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
else if (wc <= 0x7FF)
{
utf8_bytes[0] = 0xC0 | ((wc >> 6));
utf8_bytes[1] = 0x80 | (wc & 0x3F);
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
utf8_bytes_filled = 2;
}
else if (0xD800 > wc or wc >= 0xE000)
{
utf8_bytes[0] = 0xE0 | ((wc >> 12));
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
utf8_bytes[2] = 0x80 | (wc & 0x3F);
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
utf8_bytes_filled = 3;
}
else
{
if (current_wchar < str.size())
{
const auto wc2 = static_cast<int>(str[current_wchar++]);
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
utf8_bytes[0] = 0xf0 | (charcode >> 18);
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
utf8_bytes_filled = 4;
}
else
{
// unknown character
++current_wchar;
utf8_bytes[0] = wc;
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
utf8_bytes_filled = 1;
}
}
@ -269,7 +286,7 @@ template<typename WideStringType>
class wide_string_input_adapter : public input_adapter_protocol
{
public:
explicit wide_string_input_adapter(const WideStringType& w) noexcept
explicit wide_string_input_adapter(const WideStringType& w) noexcept
: str(w)
{}

View File

@ -1,9 +1,10 @@
#pragma once
#include <cassert>
#include <cassert> // assert
#include <cstddef>
#include <string>
#include <vector>
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
@ -158,6 +159,13 @@ class json_sax_dom_parser
: root(r), allow_exceptions(allow_exceptions_)
{}
// make class move-only
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
json_sax_dom_parser(json_sax_dom_parser&&) = default;
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
~json_sax_dom_parser() = default;
bool null()
{
handle_value(nullptr);
@ -249,16 +257,16 @@ class json_sax_dom_parser
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
@ -295,18 +303,17 @@ class json_sax_dom_parser
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
return &(ref_stack.back()->m_value.array->back());
}
else
{
assert(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
assert(ref_stack.back()->is_object())
assert(object_element);
*object_element = BasicJsonType(std::forward<Value>(v));
return object_element;
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
std::vector<BasicJsonType*> ref_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred
@ -334,6 +341,13 @@ class json_sax_dom_callback_parser
keep_stack.push_back(true);
}
// make class move-only
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
~json_sax_dom_callback_parser() = default;
bool null()
{
handle_value(nullptr);
@ -380,13 +394,9 @@ class json_sax_dom_callback_parser
ref_stack.push_back(val.second);
// check object limit
if (ref_stack.back())
if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive object size: " + std::to_string(len)));
}
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
}
return true;
@ -411,13 +421,10 @@ class json_sax_dom_callback_parser
bool end_object()
{
if (ref_stack.back())
if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
{
// discard object
*ref_stack.back() = discarded;
}
// discard object
*ref_stack.back() = discarded;
}
assert(not ref_stack.empty());
@ -425,18 +432,15 @@ class json_sax_dom_callback_parser
ref_stack.pop_back();
keep_stack.pop_back();
if (not ref_stack.empty() and ref_stack.back())
if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
{
// remove discarded value
if (ref_stack.back()->is_object())
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
{
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
if (it->is_discarded())
{
if (it->is_discarded())
{
ref_stack.back()->erase(it);
break;
}
ref_stack.back()->erase(it);
break;
}
}
}
@ -453,13 +457,9 @@ class json_sax_dom_callback_parser
ref_stack.push_back(val.second);
// check array limit
if (ref_stack.back())
if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
{
JSON_THROW(out_of_range::create(408,
"excessive array size: " + std::to_string(len)));
}
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
}
return true;
@ -485,12 +485,9 @@ class json_sax_dom_callback_parser
keep_stack.pop_back();
// remove discarded value
if (not keep and not ref_stack.empty())
if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
{
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->pop_back();
}
ref_stack.back()->m_value.array->pop_back();
}
return true;
@ -506,16 +503,16 @@ class json_sax_dom_callback_parser
switch ((ex.id / 100) % 100)
{
case 1:
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
case 4:
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
// LCOV_EXCL_START
case 2:
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
case 3:
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
case 5:
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
default:
assert(false);
// LCOV_EXCL_STOP
@ -585,37 +582,38 @@ class json_sax_dom_callback_parser
// we now only expect arrays and objects
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
// array
if (ref_stack.back()->is_array())
{
ref_stack.back()->m_value.array->push_back(std::move(value));
return {true, &(ref_stack.back()->m_value.array->back())};
}
else
// object
assert(ref_stack.back()->is_object())
// check if we should store an element for the current key
assert(not key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (not store_element)
{
// check if we should store an element for the current key
assert(not key_keep_stack.empty());
const bool store_element = key_keep_stack.back();
key_keep_stack.pop_back();
if (not store_element)
{
return {false, nullptr};
}
assert(object_element);
*object_element = std::move(value);
return {true, object_element};
return {false, nullptr};
}
assert(object_element);
*object_element = std::move(value);
return {true, object_element};
}
/// the parsed JSON value
BasicJsonType& root;
/// stack to model hierarchy of values
std::vector<BasicJsonType*> ref_stack;
std::vector<BasicJsonType*> ref_stack {};
/// stack to manage which values to keep
std::vector<bool> keep_stack;
std::vector<bool> keep_stack {};
/// stack to manage which object keys to keep
std::vector<bool> key_keep_stack;
std::vector<bool> key_keep_stack {};
/// helper to hold the reference for the next object element
BasicJsonType* object_element = nullptr;
/// whether a syntax error occurred

View File

@ -1,16 +1,18 @@
#pragma once
#include <array> // array
#include <clocale> // localeconv
#include <cstddef> // size_t
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <cstdio> // snprintf
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
#include <initializer_list> // initializer_list
#include <string> // char_traits, string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/position_t.hpp>
#include <nlohmann/detail/macro_scope.hpp>
namespace nlohmann
{
@ -148,22 +150,22 @@ class lexer
assert(current == 'u');
int codepoint = 0;
const auto factors = { 12, 8, 4, 0 };
const auto factors = { 12u, 8u, 4u, 0u };
for (const auto factor : factors)
{
get();
if (current >= '0' and current <= '9')
{
codepoint += ((current - 0x30) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
}
else if (current >= 'A' and current <= 'F')
{
codepoint += ((current - 0x37) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
}
else if (current >= 'a' and current <= 'f')
{
codepoint += ((current - 0x57) << factor);
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
}
else
{
@ -321,15 +323,15 @@ class lexer
if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
{
// overwrite codepoint
codepoint =
// high surrogate occupies the most significant 22 bits
(codepoint1 << 10)
// low surrogate occupies the least significant 15 bits
+ codepoint2
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00;
codepoint = static_cast<int>(
// high surrogate occupies the most significant 22 bits
(static_cast<unsigned int>(codepoint1) << 10u)
// low surrogate occupies the least significant 15 bits
+ static_cast<unsigned int>(codepoint2)
// there is still the 0xD800, 0xDC00 and 0x10000 noise
// in the result so we have to subtract with:
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
- 0x35FDC00u);
}
else
{
@ -364,23 +366,23 @@ class lexer
else if (codepoint <= 0x7FF)
{
// 2-byte characters: 110xxxxx 10xxxxxx
add(0xC0 | (codepoint >> 6));
add(0x80 | (codepoint & 0x3F));
add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
}
else if (codepoint <= 0xFFFF)
{
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
add(0xE0 | (codepoint >> 12));
add(0x80 | ((codepoint >> 6) & 0x3F));
add(0x80 | (codepoint & 0x3F));
add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
}
else
{
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
add(0xF0 | (codepoint >> 18));
add(0x80 | ((codepoint >> 12) & 0x3F));
add(0x80 | ((codepoint >> 6) & 0x3F));
add(0x80 | (codepoint & 0x3F));
add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
}
break;
@ -906,13 +908,9 @@ class lexer
goto scan_number_any1;
}
// LCOV_EXCL_START
default:
{
// all other characters are rejected outside scan_number()
assert(false);
}
// LCOV_EXCL_STOP
// all other characters are rejected outside scan_number()
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
scan_number_minus:
@ -1297,7 +1295,7 @@ scan_number_done:
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
{
assert(token_string.size() != 0);
assert(not token_string.empty());
token_string.pop_back();
}
}
@ -1359,9 +1357,9 @@ scan_number_done:
if ('\x00' <= c and c <= '\x1F')
{
// escape control characters
char cs[9];
(std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
result += cs;
std::array<char, 9> cs{};
(std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
result += cs.data();
}
else
{
@ -1483,7 +1481,7 @@ scan_number_done:
bool next_unget = false;
/// the start position of the current token
position_t position;
position_t position {};
/// raw input token string (for error messages)
std::vector<char> token_string {};

View File

@ -6,13 +6,14 @@
#include <functional> // function
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/json_sax.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/is_sax.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@ -458,7 +459,7 @@ class parser
/// get next token from lexer
token_type get_token()
{
return (last_token = m_lexer.scan());
return last_token = m_lexer.scan();
}
std::string exception_message(const token_type expected, const std::string& context)

View File

@ -23,5 +23,5 @@ struct position_t
}
};
}
}
} // namespace detail
} // namespace nlohmann

View File

@ -607,7 +607,7 @@ class iter_impl
/// associated JSON instance
pointer m_object = nullptr;
/// the actual iterator of the associated instance
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
};
} // namespace detail
} // namespace nlohmann
} // namespace nlohmann

View File

@ -1,12 +1,12 @@
#pragma once
#include <cstddef> // size_t
#include <string> // string, to_string
#include <iterator> // input_iterator_tag
#include <string> // string, to_string
#include <tuple> // tuple_size, get, tuple_element
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
{
@ -147,6 +147,11 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
// And see https://github.com/nlohmann/json/pull/1391
namespace std
{
#if defined(__clang__)
// Fix: https://github.com/nlohmann/json/issues/1401
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wmismatched-tags"
#endif
template <typename IteratorType>
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
: public std::integral_constant<std::size_t, 2> {};
@ -159,4 +164,7 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
get<N>(std::declval <
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
};
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif
} // namespace std

View File

@ -45,5 +45,5 @@ struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
using pointer = T*;
using reference = T&;
};
}
}
} // namespace detail
} // namespace nlohmann

View File

@ -4,10 +4,11 @@
#include <cassert> // assert
#include <numeric> // accumulate
#include <string> // string
#include <utility> // move
#include <vector> // vector
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/value_t.hpp>
namespace nlohmann
@ -76,6 +77,139 @@ class json_pointer
return to_string();
}
/*!
@brief append another JSON pointer at the end of this JSON pointer
*/
json_pointer& operator/=(const json_pointer& ptr)
{
reference_tokens.insert(reference_tokens.end(),
ptr.reference_tokens.begin(),
ptr.reference_tokens.end());
return *this;
}
/// @copydoc push_back(std::string&&)
json_pointer& operator/=(std::string token)
{
push_back(std::move(token));
return *this;
}
/// @copydoc operator/=(std::string)
json_pointer& operator/=(std::size_t array_index)
{
return *this /= std::to_string(array_index);
}
/*!
@brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
*/
friend json_pointer operator/(const json_pointer& left_ptr,
const json_pointer& right_ptr)
{
return json_pointer(left_ptr) /= right_ptr;
}
/*!
@brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
*/
friend json_pointer operator/(const json_pointer& ptr, std::string token)
{
return json_pointer(ptr) /= std::move(token);
}
/*!
@brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
*/
friend json_pointer operator/(const json_pointer& lhs, std::size_t array_index)
{
return json_pointer(lhs) /= array_index;
}
/*!
@brief returns the parent of this JSON pointer
@return parent of this JSON pointer; in case this JSON pointer is the root,
the root itself is returned
@complexity Constant.
@liveexample{The example shows the result of `parent_pointer` for different
JSON Pointers.,json_pointer__parent_pointer}
@since version 3.6.0
*/
json_pointer parent_pointer() const
{
if (empty())
{
return *this;
}
json_pointer res = *this;
res.pop_back();
return res;
}
/*!
@brief remove and return last reference token
@throw out_of_range.405 if JSON pointer has no parent
*/
std::string pop_back()
{
if (JSON_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
auto last = reference_tokens.back();
reference_tokens.pop_back();
return last;
}
/*!
@brief append an unescaped token at the end of the reference pointer
@param[in] token token to add
@complexity Amortized constant.
@liveexample{The example shows the result of `push_back` for different
JSON Pointers.,json_pointer__push_back}
@since version 0.6.0
*/
void push_back(const std::string& token)
{
reference_tokens.push_back(token);
}
/// @copydoc push_back(const std::string&)
void push_back(std::string&& token)
{
reference_tokens.push_back(std::move(token));
}
/*!
@brief return whether pointer points to the root document
@return true iff the JSON pointer points to the root document
@complexity Constant.
@exceptionsafety No-throw guarantee: this function never throws exceptions.
@liveexample{The example shows the result of `empty` for different JSON
Pointers.,json_pointer__empty}
@since version 3.6.0
*/
bool empty() const noexcept
{
return reference_tokens.empty();
}
private:
/*!
@param[in] s reference token to be converted into an array index
@ -97,32 +231,9 @@ class json_pointer
return res;
}
private:
/*!
@brief remove and return last reference pointer
@throw out_of_range.405 if JSON pointer has no parent
*/
std::string pop_back()
{
if (JSON_UNLIKELY(is_root()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
auto last = reference_tokens.back();
reference_tokens.pop_back();
return last;
}
/// return whether pointer points to the root document
bool is_root() const noexcept
{
return reference_tokens.empty();
}
json_pointer top() const
{
if (JSON_UNLIKELY(is_root()))
if (JSON_UNLIKELY(empty()))
{
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
}
@ -233,7 +344,7 @@ class json_pointer
std::all_of(reference_token.begin(), reference_token.end(),
[](const char x)
{
return (x >= '0' and x <= '9');
return x >= '0' and x <= '9';
});
// change value to array for numbers or "-" or to object otherwise
@ -682,7 +793,7 @@ class json_pointer
friend bool operator==(json_pointer const& lhs,
json_pointer const& rhs) noexcept
{
return (lhs.reference_tokens == rhs.reference_tokens);
return lhs.reference_tokens == rhs.reference_tokens;
}
friend bool operator!=(json_pointer const& lhs,

View File

@ -1,5 +1,7 @@
#pragma once
#include <utility> // pair
// This file contains all internal macro definitions
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
@ -37,6 +39,19 @@
#define JSON_DEPRECATED
#endif
// allow for portable nodiscard warnings
#if defined(__has_cpp_attribute)
#if __has_cpp_attribute(nodiscard)
#define JSON_NODISCARD [[nodiscard]]
#elif __has_cpp_attribute(gnu::warn_unused_result)
#define JSON_NODISCARD [[gnu::warn_unused_result]]
#else
#define JSON_NODISCARD
#endif
#else
#define JSON_NODISCARD
#endif
// allow to disable exceptions
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
#define JSON_THROW(exception) throw exception
@ -44,6 +59,7 @@
#define JSON_CATCH(exception) catch(exception)
#define JSON_INTERNAL_CATCH(exception) catch(exception)
#else
#include <cstdlib>
#define JSON_THROW(exception) std::abort()
#define JSON_TRY if(true)
#define JSON_CATCH(exception) if(false)
@ -72,8 +88,8 @@
// manual branch prediction
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
#define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
#define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
#define JSON_LIKELY(x) __builtin_expect(static_cast<bool>(x), 1)
#define JSON_UNLIKELY(x) __builtin_expect(static_cast<bool>(x), 0)
#else
#define JSON_LIKELY(x) x
#define JSON_UNLIKELY(x) x

View File

@ -16,6 +16,7 @@
#undef JSON_LIKELY
#undef JSON_UNLIKELY
#undef JSON_DEPRECATED
#undef JSON_NODISCARD
#undef JSON_HAS_CPP_14
#undef JSON_HAS_CPP_17
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION

View File

@ -14,7 +14,9 @@ struct nonesuch
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
nonesuch(nonesuch const&&) = delete;
void operator=(nonesuch const&) = delete;
void operator=(nonesuch&&) = delete;
};
template <class Default,

View File

@ -2,6 +2,7 @@
#include <cstdint> // size_t
#include <utility> // declval
#include <string> // string
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>

View File

@ -5,11 +5,11 @@
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
#include <utility> // declval
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/iterators/iterator_traits.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/detected.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/json_fwd.hpp>
namespace nlohmann
{

View File

@ -5,6 +5,7 @@
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
#include <cstring> // memcpy
#include <limits> // numeric_limits
#include <string> // string
#include <nlohmann/detail/input/binary_reader.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
@ -87,27 +88,27 @@ class binary_writer
// code from the value_t::number_unsigned case here.
if (j.m_value.number_integer <= 0x17)
{
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else
{
oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
}
else
@ -117,27 +118,27 @@ class binary_writer
const auto positive_number = -1 - j.m_value.number_integer;
if (j.m_value.number_integer >= -24)
{
write_number(static_cast<uint8_t>(0x20 + positive_number));
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
}
else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x38));
write_number(static_cast<uint8_t>(positive_number));
write_number(static_cast<std::uint8_t>(positive_number));
}
else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x39));
write_number(static_cast<uint16_t>(positive_number));
write_number(static_cast<std::uint16_t>(positive_number));
}
else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x3A));
write_number(static_cast<uint32_t>(positive_number));
write_number(static_cast<std::uint32_t>(positive_number));
}
else
{
oa->write_character(to_char_type(0x3B));
write_number(static_cast<uint64_t>(positive_number));
write_number(static_cast<std::uint64_t>(positive_number));
}
}
break;
@ -147,27 +148,27 @@ class binary_writer
{
if (j.m_value.number_unsigned <= 0x17)
{
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x18));
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x19));
write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x1A));
write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
}
else
{
oa->write_character(to_char_type(0x1B));
write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
}
break;
}
@ -185,28 +186,28 @@ class binary_writer
const auto N = j.m_value.string->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0x60 + N));
write_number(static_cast<std::uint8_t>(0x60 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x78));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x79));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x7A));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0x7B));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -223,28 +224,28 @@ class binary_writer
const auto N = j.m_value.array->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0x80 + N));
write_number(static_cast<std::uint8_t>(0x80 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0x98));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0x99));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0x9A));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0x9B));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -262,28 +263,28 @@ class binary_writer
const auto N = j.m_value.object->size();
if (N <= 0x17)
{
write_number(static_cast<uint8_t>(0xA0 + N));
write_number(static_cast<std::uint8_t>(0xA0 + N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
oa->write_character(to_char_type(0xB8));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
oa->write_character(to_char_type(0xB9));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
oa->write_character(to_char_type(0xBA));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// LCOV_EXCL_START
else if (N <= (std::numeric_limits<uint64_t>::max)())
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
{
oa->write_character(to_char_type(0xBB));
write_number(static_cast<uint64_t>(N));
write_number(static_cast<std::uint64_t>(N));
}
// LCOV_EXCL_STOP
@ -332,31 +333,31 @@ class binary_writer
if (j.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
}
else
@ -364,35 +365,35 @@ class binary_writer
if (j.m_value.number_integer >= -32)
{
// negative fixnum
write_number(static_cast<int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
{
// int 8
oa->write_character(to_char_type(0xD0));
write_number(static_cast<int8_t>(j.m_value.number_integer));
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
{
// int 16
oa->write_character(to_char_type(0xD1));
write_number(static_cast<int16_t>(j.m_value.number_integer));
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
{
// int 32
oa->write_character(to_char_type(0xD2));
write_number(static_cast<int32_t>(j.m_value.number_integer));
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
{
// int 64
oa->write_character(to_char_type(0xD3));
write_number(static_cast<int64_t>(j.m_value.number_integer));
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
}
}
break;
@ -403,31 +404,31 @@ class binary_writer
if (j.m_value.number_unsigned < 128)
{
// positive fixnum
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
// uint 8
oa->write_character(to_char_type(0xCC));
write_number(static_cast<uint8_t>(j.m_value.number_integer));
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
{
// uint 16
oa->write_character(to_char_type(0xCD));
write_number(static_cast<uint16_t>(j.m_value.number_integer));
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
{
// uint 32
oa->write_character(to_char_type(0xCE));
write_number(static_cast<uint32_t>(j.m_value.number_integer));
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
}
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
{
// uint 64
oa->write_character(to_char_type(0xCF));
write_number(static_cast<uint64_t>(j.m_value.number_integer));
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
}
break;
}
@ -446,25 +447,25 @@ class binary_writer
if (N <= 31)
{
// fixstr
write_number(static_cast<uint8_t>(0xA0 | N));
write_number(static_cast<std::uint8_t>(0xA0 | N));
}
else if (N <= (std::numeric_limits<uint8_t>::max)())
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
{
// str 8
oa->write_character(to_char_type(0xD9));
write_number(static_cast<uint8_t>(N));
write_number(static_cast<std::uint8_t>(N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// str 16
oa->write_character(to_char_type(0xDA));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// str 32
oa->write_character(to_char_type(0xDB));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write the string
@ -481,19 +482,19 @@ class binary_writer
if (N <= 15)
{
// fixarray
write_number(static_cast<uint8_t>(0x90 | N));
write_number(static_cast<std::uint8_t>(0x90 | N));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// array 16
oa->write_character(to_char_type(0xDC));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// array 32
oa->write_character(to_char_type(0xDD));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write each element
@ -511,19 +512,19 @@ class binary_writer
if (N <= 15)
{
// fixmap
write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
}
else if (N <= (std::numeric_limits<uint16_t>::max)())
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
{
// map 16
oa->write_character(to_char_type(0xDE));
write_number(static_cast<uint16_t>(N));
write_number(static_cast<std::uint16_t>(N));
}
else if (N <= (std::numeric_limits<uint32_t>::max)())
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
{
// map 32
oa->write_character(to_char_type(0xDF));
write_number(static_cast<uint32_t>(N));
write_number(static_cast<std::uint32_t>(N));
}
// step 2: write each element
@ -789,14 +790,9 @@ class binary_writer
*/
static std::size_t calc_bson_integer_size(const std::int64_t value)
{
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
{
return sizeof(std::int32_t);
}
else
{
return sizeof(std::int64_t);
}
return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
? sizeof(std::int32_t)
: sizeof(std::int64_t);
}
/*!
@ -1064,45 +1060,45 @@ class binary_writer
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix)
{
if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('i')); // int8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if (n <= (std::numeric_limits<uint8_t>::max)())
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('U')); // uint8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('I')); // int16
}
write_number(static_cast<int16_t>(n));
write_number(static_cast<std::int16_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('l')); // int32
}
write_number(static_cast<int32_t>(n));
write_number(static_cast<std::int32_t>(n));
}
else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('L')); // int64
}
write_number(static_cast<int64_t>(n));
write_number(static_cast<std::int64_t>(n));
}
else
{
@ -1117,45 +1113,45 @@ class binary_writer
void write_number_with_ubjson_prefix(const NumberType n,
const bool add_prefix)
{
if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('i')); // int8
}
write_number(static_cast<int8_t>(n));
write_number(static_cast<std::int8_t>(n));
}
else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
{
if (add_prefix)
{
oa->write_character(to_char_type('U')); // uint8
}
write_number(static_cast<uint8_t>(n));
write_number(static_cast<std::uint8_t>(n));
}
else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('I')); // int16
}
write_number(static_cast<int16_t>(n));
write_number(static_cast<std::int16_t>(n));
}
else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('l')); // int32
}
write_number(static_cast<int32_t>(n));
write_number(static_cast<std::int32_t>(n));
}
else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
{
if (add_prefix)
{
oa->write_character(to_char_type('L')); // int64
}
write_number(static_cast<int64_t>(n));
write_number(static_cast<std::int64_t>(n));
}
// LCOV_EXCL_START
else
@ -1186,19 +1182,19 @@ class binary_writer
case value_t::number_integer:
{
if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
{
return 'i';
}
if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
{
return 'U';
}
if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
{
return 'I';
}
if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
{
return 'l';
}
@ -1208,19 +1204,19 @@ class binary_writer
case value_t::number_unsigned:
{
if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int8_t>::max)())
{
return 'i';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
{
return 'U';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int16_t>::max)())
{
return 'I';
}
if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int32_t>::max)())
{
return 'l';
}
@ -1278,7 +1274,7 @@ class binary_writer
std::memcpy(vec.data(), &n, sizeof(NumberType));
// step 2: write array to output (with possible reordering)
if (is_little_endian and not OutputIsLittleEndian)
if (is_little_endian != OutputIsLittleEndian)
{
// reverse byte order prior to conversion if necessary
std::reverse(vec.begin(), vec.end());

View File

@ -12,9 +12,10 @@
#include <limits> // numeric_limits
#include <string> // string
#include <type_traits> // is_same
#include <utility> // move
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/conversions/to_chars.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/output/binary_writer.hpp>
@ -44,8 +45,8 @@ class serializer
using number_float_t = typename BasicJsonType::number_float_t;
using number_integer_t = typename BasicJsonType::number_integer_t;
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
static constexpr uint8_t UTF8_ACCEPT = 0;
static constexpr uint8_t UTF8_REJECT = 1;
static constexpr std::uint8_t UTF8_ACCEPT = 0;
static constexpr std::uint8_t UTF8_REJECT = 1;
public:
/*!
@ -277,6 +278,9 @@ class serializer
o->write_characters("null", 4);
return;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
}
@ -297,8 +301,8 @@ class serializer
*/
void dump_escaped(const string_t& s, const bool ensure_ascii)
{
uint32_t codepoint;
uint8_t state = UTF8_ACCEPT;
std::uint32_t codepoint;
std::uint8_t state = UTF8_ACCEPT;
std::size_t bytes = 0; // number of bytes written to string_buffer
// number of bytes written at the point of the last valid byte
@ -373,14 +377,14 @@ class serializer
if (codepoint <= 0xFFFF)
{
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
static_cast<uint16_t>(codepoint));
static_cast<std::uint16_t>(codepoint));
bytes += 6;
}
else
{
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
bytes += 12;
}
}
@ -454,6 +458,16 @@ class serializer
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
}
// write buffer and reset index; there must be 13 bytes
// left, as this is the maximal number of bytes to be
// written ("\uxxxx\uxxxx\0") for one code point
if (string_buffer.size() - bytes < 13)
{
o->write_characters(string_buffer.data(), bytes);
bytes = 0;
}
bytes_after_last_accept = bytes;
}
@ -463,6 +477,9 @@ class serializer
state = UTF8_ACCEPT;
break;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
break;
}
@ -497,7 +514,7 @@ class serializer
case error_handler_t::strict:
{
std::string sn(3, '\0');
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
}
@ -523,6 +540,9 @@ class serializer
}
break;
}
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
}
}
@ -579,16 +599,16 @@ class serializer
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
{
{
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
{'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
{'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
{'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
{'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
{'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
{'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'},
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
}
};
@ -600,7 +620,7 @@ class serializer
}
// use a pointer to fill the buffer
auto buffer_ptr = begin(number_buffer);
auto buffer_ptr = number_buffer.begin();
const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
number_unsigned_t abs_value;
@ -610,7 +630,7 @@ class serializer
if (is_negative)
{
*buffer_ptr = '-';
abs_value = static_cast<number_unsigned_t>(0 - x);
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
// account one more byte for the minus sign
n_chars = 1 + count_digits(abs_value);
@ -630,7 +650,6 @@ class serializer
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
const auto buffer_end = buffer_ptr;
while (abs_value >= 100)
{
const auto digits_index = static_cast<unsigned>((abs_value % 100));
@ -730,7 +749,7 @@ class serializer
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
[](char c)
{
return (c == '.' or c == 'e');
return c == '.' or c == 'e';
});
if (value_is_int_like)
@ -760,9 +779,9 @@ class serializer
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
*/
static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
{
static const std::array<uint8_t, 400> utf8d =
static const std::array<std::uint8_t, 400> utf8d =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
@ -782,11 +801,11 @@ class serializer
}
};
const uint8_t type = utf8d[byte];
const std::uint8_t type = utf8d[byte];
codep = (state != UTF8_ACCEPT)
? (byte & 0x3fu) | (codep << 6)
: static_cast<uint32_t>(0xff >> type) & (byte);
? (byte & 0x3fu) | (codep << 6u)
: (0xFFu >> type) & (byte);
state = utf8d[256u + state * 16u + type];
return state;

View File

@ -4,6 +4,7 @@
#include <ciso646> // and
#include <cstddef> // size_t
#include <cstdint> // uint8_t
#include <string> // string
namespace nlohmann
{

View File

@ -27,8 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef NLOHMANN_JSON_HPP
#define NLOHMANN_JSON_HPP
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
#define INCLUDE_NLOHMANN_JSON_HPP_
#define NLOHMANN_JSON_VERSION_MAJOR 3
#define NLOHMANN_JSON_VERSION_MINOR 5
@ -42,33 +42,35 @@ SOFTWARE.
#include <initializer_list> // initializer_list
#include <iosfwd> // istream, ostream
#include <iterator> // random_access_iterator_tag
#include <memory> // unique_ptr
#include <numeric> // accumulate
#include <string> // string, stoi, to_string
#include <utility> // declval, forward, move, pair, swap
#include <vector> // vector
#include <nlohmann/json_fwd.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/adl_serializer.hpp>
#include <nlohmann/detail/conversions/from_json.hpp>
#include <nlohmann/detail/conversions/to_json.hpp>
#include <nlohmann/detail/exceptions.hpp>
#include <nlohmann/detail/input/binary_reader.hpp>
#include <nlohmann/detail/input/input_adapters.hpp>
#include <nlohmann/detail/input/lexer.hpp>
#include <nlohmann/detail/input/parser.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/iterators/internal_iterator.hpp>
#include <nlohmann/detail/iterators/iter_impl.hpp>
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
#include <nlohmann/detail/input/binary_reader.hpp>
#include <nlohmann/detail/output/binary_writer.hpp>
#include <nlohmann/detail/output/serializer.hpp>
#include <nlohmann/detail/json_ref.hpp>
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
#include <nlohmann/detail/json_pointer.hpp>
#include <nlohmann/adl_serializer.hpp>
#include <nlohmann/detail/json_ref.hpp>
#include <nlohmann/detail/macro_scope.hpp>
#include <nlohmann/detail/meta/cpp_future.hpp>
#include <nlohmann/detail/meta/type_traits.hpp>
#include <nlohmann/detail/output/binary_writer.hpp>
#include <nlohmann/detail/output/output_adapters.hpp>
#include <nlohmann/detail/output/serializer.hpp>
#include <nlohmann/detail/value_t.hpp>
#include <nlohmann/json_fwd.hpp>
/*!
@brief namespace for Niels Lohmann
@ -317,6 +319,7 @@ class basic_json
@since 2.1.0
*/
JSON_NODISCARD
static basic_json meta()
{
basic_json result;
@ -1322,6 +1325,8 @@ class basic_json
case value_t::discarded:
m_type = value_t::discarded;
break;
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
assert_invariant();
}
@ -1409,7 +1414,7 @@ class basic_json
bool is_an_object = std::all_of(init.begin(), init.end(),
[](const detail::json_ref<basic_json>& element_ref)
{
return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
});
// adjust type if type deduction is not wanted
@ -1489,6 +1494,7 @@ class basic_json
@since version 1.0.0
*/
JSON_NODISCARD
static basic_json array(initializer_list_t init = {})
{
return basic_json(init, false, value_t::array);
@ -1532,6 +1538,7 @@ class basic_json
@since version 1.0.0
*/
JSON_NODISCARD
static basic_json object(initializer_list_t init = {})
{
return basic_json(init, false, value_t::object);
@ -2092,7 +2099,7 @@ class basic_json
*/
constexpr bool is_null() const noexcept
{
return (m_type == value_t::null);
return m_type == value_t::null;
}
/*!
@ -2114,7 +2121,7 @@ class basic_json
*/
constexpr bool is_boolean() const noexcept
{
return (m_type == value_t::boolean);
return m_type == value_t::boolean;
}
/*!
@ -2173,7 +2180,7 @@ class basic_json
*/
constexpr bool is_number_integer() const noexcept
{
return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
}
/*!
@ -2201,7 +2208,7 @@ class basic_json
*/
constexpr bool is_number_unsigned() const noexcept
{
return (m_type == value_t::number_unsigned);
return m_type == value_t::number_unsigned;
}
/*!
@ -2229,7 +2236,7 @@ class basic_json
*/
constexpr bool is_number_float() const noexcept
{
return (m_type == value_t::number_float);
return m_type == value_t::number_float;
}
/*!
@ -2251,7 +2258,7 @@ class basic_json
*/
constexpr bool is_object() const noexcept
{
return (m_type == value_t::object);
return m_type == value_t::object;
}
/*!
@ -2273,7 +2280,7 @@ class basic_json
*/
constexpr bool is_array() const noexcept
{
return (m_type == value_t::array);
return m_type == value_t::array;
}
/*!
@ -2295,7 +2302,7 @@ class basic_json
*/
constexpr bool is_string() const noexcept
{
return (m_type == value_t::string);
return m_type == value_t::string;
}
/*!
@ -2322,7 +2329,7 @@ class basic_json
*/
constexpr bool is_discarded() const noexcept
{
return (m_type == value_t::discarded);
return m_type == value_t::discarded;
}
/*!
@ -2856,7 +2863,7 @@ class basic_json
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
and not std::is_same<ValueType, typename std::string_view>::value
#endif
#endif
@ -3894,6 +3901,8 @@ class basic_json
@liveexample{The example shows how `find()` is used.,find__key_type}
@sa @ref contains(KeyT&&) const -- checks whether a key exists
@since version 1.0.0
*/
template<typename KeyT>
@ -3954,6 +3963,36 @@ class basic_json
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
}
/*!
@brief check the existence of an element in a JSON object
Check whether an element exists in a JSON object with key equivalent to
@a key. If the element is not found or the JSON value is not an object,
false is returned.
@note This method always returns false when executed on a JSON type
that is not an object.
@param[in] key key value to check its existence.
@return true if an element with specified @a key exists. If no such
element with such key is found or the JSON value is not an object,
false is returned.
@complexity Logarithmic in the size of the JSON object.
@liveexample{The following code shows an example for `contains()`.,contains}
@sa @ref find(KeyT&&) -- returns an iterator to an object element
@since version 3.6.0
*/
template<typename KeyT>
bool contains(KeyT&& key) const
{
return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
}
/// @}
@ -5530,28 +5569,28 @@ class basic_json
switch (lhs_type)
{
case value_t::array:
return (*lhs.m_value.array == *rhs.m_value.array);
return *lhs.m_value.array == *rhs.m_value.array;
case value_t::object:
return (*lhs.m_value.object == *rhs.m_value.object);
return *lhs.m_value.object == *rhs.m_value.object;
case value_t::null:
return true;
case value_t::string:
return (*lhs.m_value.string == *rhs.m_value.string);
return *lhs.m_value.string == *rhs.m_value.string;
case value_t::boolean:
return (lhs.m_value.boolean == rhs.m_value.boolean);
return lhs.m_value.boolean == rhs.m_value.boolean;
case value_t::number_integer:
return (lhs.m_value.number_integer == rhs.m_value.number_integer);
return lhs.m_value.number_integer == rhs.m_value.number_integer;
case value_t::number_unsigned:
return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
case value_t::number_float:
return (lhs.m_value.number_float == rhs.m_value.number_float);
return lhs.m_value.number_float == rhs.m_value.number_float;
default:
return false;
@ -5559,27 +5598,27 @@ class basic_json
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
{
return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
}
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
{
return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
}
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
{
return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
}
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
{
return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
}
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
{
return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
}
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
{
return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
}
return false;
@ -5593,7 +5632,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs == basic_json(rhs));
return lhs == basic_json(rhs);
}
/*!
@ -5604,7 +5643,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) == rhs);
return basic_json(lhs) == rhs;
}
/*!
@ -5638,7 +5677,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs != basic_json(rhs));
return lhs != basic_json(rhs);
}
/*!
@ -5649,7 +5688,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) != rhs);
return basic_json(lhs) != rhs;
}
/*!
@ -5688,7 +5727,7 @@ class basic_json
switch (lhs_type)
{
case value_t::array:
return (*lhs.m_value.array) < (*rhs.m_value.array);
return *lhs.m_value.array < *rhs.m_value.array;
case value_t::object:
return *lhs.m_value.object < *rhs.m_value.object;
@ -5754,7 +5793,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs < basic_json(rhs));
return lhs < basic_json(rhs);
}
/*!
@ -5765,7 +5804,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) < rhs);
return basic_json(lhs) < rhs;
}
/*!
@ -5800,7 +5839,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs <= basic_json(rhs));
return lhs <= basic_json(rhs);
}
/*!
@ -5811,7 +5850,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) <= rhs);
return basic_json(lhs) <= rhs;
}
/*!
@ -5846,7 +5885,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs > basic_json(rhs));
return lhs > basic_json(rhs);
}
/*!
@ -5857,7 +5896,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) > rhs);
return basic_json(lhs) > rhs;
}
/*!
@ -5892,7 +5931,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
{
return (lhs >= basic_json(rhs));
return lhs >= basic_json(rhs);
}
/*!
@ -5903,7 +5942,7 @@ class basic_json
std::is_scalar<ScalarType>::value, int>::type = 0>
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
{
return (basic_json(lhs) >= rhs);
return basic_json(lhs) >= rhs;
}
/// @}
@ -5949,8 +5988,8 @@ class basic_json
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
{
// read width member and use it as indentation parameter if nonzero
const bool pretty_print = (o.width() > 0);
const auto indentation = (pretty_print ? o.width() : 0);
const bool pretty_print = o.width() > 0;
const auto indentation = pretty_print ? o.width() : 0;
// reset width to 0 for subsequent calls to this stream
o.width(0);
@ -6006,9 +6045,6 @@ class basic_json
@pre The container storage is contiguous. Violating this precondition
yields undefined behavior. **This precondition is enforced with an
assertion.**
@pre Each element of the container has a size of 1 byte. Violating this
precondition yields undefined behavior. **This precondition is enforced
with a static assertion.**
@warning There is no way to enforce all preconditions at compile-time. If
the function is called with a noncompliant container and with
@ -6051,6 +6087,7 @@ class basic_json
@since version 2.0.3 (contiguous containers)
*/
JSON_NODISCARD
static basic_json parse(detail::input_adapter&& i,
const parser_callback_t cb = nullptr,
const bool allow_exceptions = true)
@ -6088,9 +6125,6 @@ class basic_json
@pre The container storage is contiguous. Violating this precondition
yields undefined behavior. **This precondition is enforced with an
assertion.**
@pre Each element of the container has a size of 1 byte. Violating this
precondition yields undefined behavior. **This precondition is enforced
with a static assertion.**
@warning There is no way to enforce all preconditions at compile-time. If
the function is called with a noncompliant container and with
@ -6127,13 +6161,9 @@ class basic_json
const bool strict = true)
{
assert(sax);
switch (format)
{
case input_format_t::json:
return parser(std::move(i)).sax_parse(sax, strict);
default:
return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
}
return format == input_format_t::json
? parser(std::move(i)).sax_parse(sax, strict)
: detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
}
/*!
@ -6826,6 +6856,7 @@ class basic_json
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
since 3.2.0
*/
JSON_NODISCARD
static basic_json from_cbor(detail::input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true)
@ -6841,6 +6872,7 @@ class basic_json
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
JSON_NODISCARD
static basic_json from_cbor(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
@ -6933,6 +6965,7 @@ class basic_json
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
since 3.2.0
*/
JSON_NODISCARD
static basic_json from_msgpack(detail::input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true)
@ -6948,6 +6981,7 @@ class basic_json
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
JSON_NODISCARD
static basic_json from_msgpack(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
@ -7019,6 +7053,7 @@ class basic_json
@since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
*/
JSON_NODISCARD
static basic_json from_ubjson(detail::input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true)
@ -7034,6 +7069,7 @@ class basic_json
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
JSON_NODISCARD
static basic_json from_ubjson(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
@ -7104,6 +7140,7 @@ class basic_json
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
related UBJSON format
*/
JSON_NODISCARD
static basic_json from_bson(detail::input_adapter&& i,
const bool strict = true,
const bool allow_exceptions = true)
@ -7119,6 +7156,7 @@ class basic_json
*/
template<typename A1, typename A2,
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
JSON_NODISCARD
static basic_json from_bson(A1 && a1, A2 && a2,
const bool strict = true,
const bool allow_exceptions = true)
@ -7454,63 +7492,58 @@ class basic_json
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
{
// adding to the root of the target document means replacing it
if (ptr.is_root())
if (ptr.empty())
{
result = val;
return;
}
else
// make sure the top element of the pointer exists
json_pointer top_pointer = ptr.top();
if (top_pointer != ptr)
{
// make sure the top element of the pointer exists
json_pointer top_pointer = ptr.top();
if (top_pointer != ptr)
result.at(top_pointer);
}
// get reference to parent of JSON pointer ptr
const auto last_path = ptr.pop_back();
basic_json& parent = result[ptr];
switch (parent.m_type)
{
case value_t::null:
case value_t::object:
{
result.at(top_pointer);
// use operator[] to add value
parent[last_path] = val;
break;
}
// get reference to parent of JSON pointer ptr
const auto last_path = ptr.pop_back();
basic_json& parent = result[ptr];
switch (parent.m_type)
case value_t::array:
{
case value_t::null:
case value_t::object:
if (last_path == "-")
{
// use operator[] to add value
parent[last_path] = val;
break;
// special case: append to back
parent.push_back(val);
}
case value_t::array:
else
{
if (last_path == "-")
const auto idx = json_pointer::array_index(last_path);
if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
{
// special case: append to back
parent.push_back(val);
// avoid undefined behavior
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
else
{
const auto idx = json_pointer::array_index(last_path);
if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
{
// avoid undefined behavior
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
}
// default case: insert add offset
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
}
break;
// default case: insert add offset
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
}
// LCOV_EXCL_START
default:
{
// if there exists a parent it cannot be primitive
assert(false);
}
// LCOV_EXCL_STOP
break;
}
// if there exists a parent it cannot be primitive
default: // LCOV_EXCL_LINE
assert(false); // LCOV_EXCL_LINE
}
};
@ -7665,7 +7698,7 @@ class basic_json
break;
}
case patch_operations::invalid:
default:
{
// op must be "add", "remove", "replace", "move", "copy", or
// "test"
@ -7710,6 +7743,7 @@ class basic_json
@since version 2.0.0
*/
JSON_NODISCARD
static basic_json diff(const basic_json& source, const basic_json& target,
const std::string& path = "")
{
@ -7729,106 +7763,105 @@ class basic_json
{
{"op", "replace"}, {"path", path}, {"value", target}
});
return result;
}
else
switch (source.type())
{
switch (source.type())
case value_t::array:
{
case value_t::array:
// first pass: traverse common elements
std::size_t i = 0;
while (i < source.size() and i < target.size())
{
// first pass: traverse common elements
std::size_t i = 0;
while (i < source.size() and i < target.size())
{
// recursive call to compare array values at index i
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
++i;
}
// i now reached the end of at least one array
// in a second pass, traverse the remaining elements
// remove my remaining elements
const auto end_index = static_cast<difference_type>(result.size());
while (i < source.size())
{
// add operations in reverse order to avoid invalid
// indices
result.insert(result.begin() + end_index, object(
{
{"op", "remove"},
{"path", path + "/" + std::to_string(i)}
}));
++i;
}
// add other remaining elements
while (i < target.size())
{
result.push_back(
{
{"op", "add"},
{"path", path + "/" + std::to_string(i)},
{"value", target[i]}
});
++i;
}
break;
// recursive call to compare array values at index i
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
++i;
}
case value_t::object:
// i now reached the end of at least one array
// in a second pass, traverse the remaining elements
// remove my remaining elements
const auto end_index = static_cast<difference_type>(result.size());
while (i < source.size())
{
// first pass: traverse this object's elements
for (auto it = source.cbegin(); it != source.cend(); ++it)
// add operations in reverse order to avoid invalid
// indices
result.insert(result.begin() + end_index, object(
{
// escape the key name to be used in a JSON patch
const auto key = json_pointer::escape(it.key());
if (target.find(it.key()) != target.end())
{
// recursive call to compare object values at key it
auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
}
else
{
// found a key that is not in o -> remove it
result.push_back(object(
{
{"op", "remove"}, {"path", path + "/" + key}
}));
}
}
// second pass: traverse other object's elements
for (auto it = target.cbegin(); it != target.cend(); ++it)
{
if (source.find(it.key()) == source.end())
{
// found a key that is not in this -> add it
const auto key = json_pointer::escape(it.key());
result.push_back(
{
{"op", "add"}, {"path", path + "/" + key},
{"value", it.value()}
});
}
}
break;
{"op", "remove"},
{"path", path + "/" + std::to_string(i)}
}));
++i;
}
default:
// add other remaining elements
while (i < target.size())
{
// both primitive type: replace value
result.push_back(
{
{"op", "replace"}, {"path", path}, {"value", target}
{"op", "add"},
{"path", path + "/" + std::to_string(i)},
{"value", target[i]}
});
break;
++i;
}
break;
}
case value_t::object:
{
// first pass: traverse this object's elements
for (auto it = source.cbegin(); it != source.cend(); ++it)
{
// escape the key name to be used in a JSON patch
const auto key = json_pointer::escape(it.key());
if (target.find(it.key()) != target.end())
{
// recursive call to compare object values at key it
auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
}
else
{
// found a key that is not in o -> remove it
result.push_back(object(
{
{"op", "remove"}, {"path", path + "/" + key}
}));
}
}
// second pass: traverse other object's elements
for (auto it = target.cbegin(); it != target.cend(); ++it)
{
if (source.find(it.key()) == source.end())
{
// found a key that is not in this -> add it
const auto key = json_pointer::escape(it.key());
result.push_back(
{
{"op", "add"}, {"path", path + "/" + key},
{"value", it.value()}
});
}
}
break;
}
default:
{
// both primitive type: replace value
result.push_back(
{
{"op", "replace"}, {"path", path}, {"value", target}
});
break;
}
}
@ -8012,4 +8045,4 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
#include <nlohmann/detail/macro_unscope.hpp>
#endif
#endif // INCLUDE_NLOHMANN_JSON_HPP_

View File

@ -1,5 +1,5 @@
#ifndef NLOHMANN_JSON_FWD_HPP
#define NLOHMANN_JSON_FWD_HPP
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
#include <cstdint> // int64_t, uint64_t
#include <map> // map
@ -61,4 +61,4 @@ uses the standard template types.
using json = basic_json<>;
} // namespace nlohmann
#endif
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_

View File

@ -12,6 +12,7 @@ nlohmann_json_multiple_headers = declare_dependency(
include_directories: include_directories('include')
)
if not meson.is_subproject()
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
pkgc = import('pkgconfig')
@ -19,3 +20,4 @@ pkgc.generate(name: 'nlohmann_json',
version: meson.project_version(),
description: 'JSON for Modern C++'
)
endif

File diff suppressed because it is too large Load Diff

View File

@ -64,7 +64,12 @@ set_target_properties(doctest_main PROPERTIES
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
)
target_compile_features(doctest_main PUBLIC cxx_std_11)
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
target_compile_features(catch_main PUBLIC cxx_range_for)
else()
target_compile_features(catch_main PUBLIC cxx_std_11)
endif()
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake

View File

@ -111,6 +111,12 @@ struct my_allocator : std::allocator<T>
p->~T();
}
}
template <class U>
struct rebind
{
using other = my_allocator<U>;
};
};
// allows deletion of raw pointer, usually hold by json_value

View File

@ -150,7 +150,7 @@ class alt_string
}
private:
std::string str_impl;
std::string str_impl {};
friend bool ::operator<(const char*, const alt_string&);
};

View File

@ -1968,7 +1968,7 @@ TEST_CASE("all CBOR first bytes")
try
{
json::from_cbor(std::vector<uint8_t>(1, byte));
auto res = json::from_cbor(std::vector<uint8_t>(1, byte));
}
catch (const json::parse_error& e)
{

View File

@ -126,7 +126,7 @@ class SaxEventLogger
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
bool errored = false;
};

View File

@ -124,7 +124,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
return false;
}
std::vector<std::string> events;
std::vector<std::string> events {};
};
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger

View File

@ -982,6 +982,93 @@ TEST_CASE("element access 2")
}
}
}
SECTION("check existence of key in an object")
{
SECTION("existing element")
{
for (auto key :
{"integer", "unsigned", "floating", "null", "string", "boolean", "object", "array"
})
{
CHECK(j.contains(key) == true);
CHECK(j_const.contains(key) == true);
}
}
SECTION("nonexisting element")
{
CHECK(j.contains("foo") == false);
CHECK(j_const.contains("foo") == false);
}
SECTION("all types")
{
SECTION("null")
{
json j_nonobject(json::value_t::null);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("string")
{
json j_nonobject(json::value_t::string);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("object")
{
json j_nonobject(json::value_t::object);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("array")
{
json j_nonobject(json::value_t::array);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("boolean")
{
json j_nonobject(json::value_t::boolean);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (integer)")
{
json j_nonobject(json::value_t::number_integer);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (unsigned)")
{
json j_nonobject(json::value_t::number_unsigned);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
SECTION("number (floating-point)")
{
json j_nonobject(json::value_t::number_float);
const json j_nonobject_const(j_nonobject);
CHECK(j_nonobject.contains("foo") == false);
CHECK(j_nonobject_const.contains("foo") == false);
}
}
}
}
}

View File

@ -439,6 +439,7 @@ TEST_CASE("JSON pointers")
})
{
CHECK(json::json_pointer(ptr).to_string() == ptr);
CHECK(std::string(json::json_pointer(ptr)) == ptr);
}
}
@ -460,4 +461,137 @@ TEST_CASE("JSON pointers")
CHECK(j.is_object());
}
}
SECTION("empty, push, pop and parent")
{
const json j =
{
{"", "Hello"},
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99},
{"", "empty string"},
{"/", "slash"},
{"~", "tilde"},
{"~1", "tilde1"}
}
}
};
// empty json_pointer returns the root JSON-object
auto ptr = ""_json_pointer;
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// simple field access
ptr.push_back("pi");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// object and children access
const std::string answer("answer");
ptr.push_back(answer);
ptr.push_back("everything");
CHECK(!ptr.empty());
CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_back();
ptr.pop_back();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// push key which has to be encoded
ptr.push_back("object");
ptr.push_back("/");
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
CHECK(j[ptr.parent_pointer()] == j["object"]);
ptr = ptr.parent_pointer().parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
// parent-pointer of the empty json_pointer is empty
ptr = ptr.parent_pointer();
CHECK(ptr.empty());
CHECK(j[ptr] == j);
CHECK_THROWS_WITH(ptr.pop_back(),
"[json.exception.out_of_range.405] JSON pointer has no parent");
}
SECTION("operators")
{
const json j =
{
{"", "Hello"},
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{
"answer", {
{"everything", 42}
}
},
{"list", {1, 0, 2}},
{
"object", {
{"currency", "USD"},
{"value", 42.99},
{"", "empty string"},
{"/", "slash"},
{"~", "tilde"},
{"~1", "tilde1"}
}
}
};
// empty json_pointer returns the root JSON-object
auto ptr = ""_json_pointer;
CHECK(j[ptr] == j);
// simple field access
ptr = ptr / "pi";
CHECK(j[ptr] == j["pi"]);
ptr.pop_back();
CHECK(j[ptr] == j);
// object and children access
const std::string answer("answer");
ptr /= answer;
ptr = ptr / "everything";
CHECK(j[ptr] == j["answer"]["everything"]);
ptr.pop_back();
ptr.pop_back();
CHECK(j[ptr] == j);
CHECK(ptr / ""_json_pointer == ptr);
CHECK(j["/answer"_json_pointer / "/everything"_json_pointer] == j["answer"]["everything"]);
// list children access
CHECK(j["/list"_json_pointer / 1] == j["list"][1]);
// push key which has to be encoded
ptr /= "object";
ptr = ptr / "/";
CHECK(j[ptr] == j["object"]["/"]);
CHECK(ptr.to_string() == "/object/~1");
}
}

View File

@ -308,7 +308,7 @@ TEST_CASE("README" * doctest::skip())
// }
// calculate a JSON patch from two JSON values
json::diff(j_result, j_original);
auto res = json::diff(j_result, j_original);
// [
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
// { "op":"remove","path":"/hello" },

View File

@ -129,8 +129,10 @@ struct nocopy
struct Data
{
std::string a;
std::string b;
Data() = default;
Data(const std::string& a_, const std::string b_) : a(a_), b(b_) {}
std::string a {};
std::string b {};
};
void from_json(const json& j, Data& data)
@ -1705,13 +1707,81 @@ TEST_CASE("regression tests")
std::map<std::string, Data> expected
{
{"1", {"testa_1", "testb_1" }},
{"1", {"testa_1", "testb_1"}},
{"2", {"testa_2", "testb_2"}},
{"3", {"testa_3", "testb_3"}},
};
const auto data = j.get<decltype(expected)>();
CHECK(expected == data);
}
SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
{
SECTION("a bunch of -1, ensure_ascii=true")
{
json dump_test;
std::vector<char> data(300, -1);
std::vector<std::string> vec_string(300, "\\ufffd");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
}
SECTION("a bunch of -2, ensure_ascii=false")
{
json dump_test;
std::vector<char> data(500, -2);
std::vector<std::string> vec_string(500, "\xEF\xBF\xBD");
std::string s{data.data(), data.size()};
dump_test["1"] = s;
std::ostringstream os;
os << "{\"1\":\"";
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
os << "\"}";
s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
CHECK(s == os.str());
}
SECTION("test case in issue #1445")
{
nlohmann::json dump_test;
const int data[] =
{
109, 108, 103, 125, -122, -53, 115,
18, 3, 0, 102, 19, 1, 15,
-110, 13, -3, -1, -81, 32, 2,
0, 0, 0, 0, 0, 0, 0,
8, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, -80, 2,
0, 0, 96, -118, 46, -116, 46,
109, -84, -87, 108, 14, 109, -24,
-83, 13, -18, -51, -83, -52, -115,
14, 6, 32, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
64, 3, 0, 0, 0, 35, -74,
-73, 55, 57, -128, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0,
0, 0, 33, 0, 0, 0, -96,
-54, -28, -26
};
std::string s;
for (unsigned i = 0; i < sizeof(data) / sizeof(int); i++)
{
s += static_cast<char>(data[i]);
}
dump_test["1"] = s;
dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
}
}
SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
{
json j = json::parse("[-9223372036854775808]");
CHECK(j.dump() == "[-9223372036854775808]");
}
}
#if not defined(JSON_NOEXCEPTION)

View File

@ -2130,7 +2130,7 @@ TEST_CASE("all UBJSON first bytes")
try
{
json::from_ubjson(std::vector<uint8_t>(1, byte));
auto res = json::from_ubjson(std::vector<uint8_t>(1, byte));
}
catch (const json::parse_error& e)
{

View File

@ -598,9 +598,8 @@ struct pod_serializer
static void to_json(BasicJsonType& j, const T& t) noexcept
{
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
std::uint64_t value = bytes[0];
for (auto i = 1; i < 8; ++i)
value |= std::uint64_t{bytes[i]} << 8 * i;
std::uint64_t value;
std::memcpy(&value, bytes, sizeof(value));
nlohmann::to_json(j, value);
}
};

27
third_party/cpplint/LICENSE vendored 100755
View File

@ -0,0 +1,27 @@
cpplint.py and its corresponding unit tests are Copyright (C) 2009 Google Inc.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

80
third_party/cpplint/README.rst vendored 100755
View File

@ -0,0 +1,80 @@
cpplint - static code checker for C++
=====================================
.. image:: https://travis-ci.org/cpplint/cpplint.svg?branch=master
:target: https://travis-ci.org/cpplint/cpplint
.. image:: https://img.shields.io/pypi/v/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/pyversions/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/status/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/l/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/dd/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/dw/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
.. image:: https://img.shields.io/pypi/dm/cpplint.svg
:target: https://pypi.python.org/pypi/cpplint
Cpplint is a command-line tool to check C/C++ files for style issues following `Google's C++ style guide <http://google.github.io/styleguide/cppguide.html>`_.
Cpplint is developed and maintained by Google Inc. at `google/styleguide <https://github.com/google/styleguide>`_, also see see the `wikipedia entry <http://en.wikipedia.org/wiki/Cpplint>`_
While Google maintains cpplint, Google is not (very) responsive to issues and pull requests, this fork aims to be (somewhat) more open to add fixes to cpplint to enable fixes, when those fixes make cpplint usable in wider contexts.
Installation
============
To install cpplint from PyPI, run:
.. code-block:: bash
$ pip install cpplint
Then run it with:
.. code-block:: bash
$ cpplint [OPTIONS] files
For full usage instructions, run:
.. code-block:: bash
$ cpplint --help
Changes
-------
The modifications in this fork are minor fixes and cosmetic changes:
* more default extensions
* python 3 compatibility
* customizable file extensions with the --extensions argument
* continuous integration on travis
* support for recursive file discovery via the --recursive argument
* support for excluding files via --exclude
* JUnit XML output format
* Overriding repository root auto-detection via --repository
* Support ``#pragma once`` as an alternative to header include guards
Acknowledgements
----------------
Thanks to Google Inc. for open-sourcing their in-house tool.
Thanks to maintainers of the fork
* `tkruse <https://github.com/tkruse>`_
* `mattyclarkson <https://github.com/mattyclarkson>`_
* `theandrewdavis <https://github.com/theandrewdavis>`_

6583
third_party/cpplint/cpplint.py vendored 100755

File diff suppressed because it is too large Load Diff