Merge branch 'develop' into doctest
This commit is contained in:
commit
365944b0bc
60 changed files with 15683 additions and 7958 deletions
23
.clang-tidy
Normal file
23
.clang-tidy
Normal 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
|
32
.travis.yml
32
.travis.yml
|
@ -128,21 +128,6 @@ matrix:
|
||||||
|
|
||||||
# OSX / Clang
|
# 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
|
- os: osx
|
||||||
osx_image: xcode8.3
|
osx_image: xcode8.3
|
||||||
|
|
||||||
|
@ -164,6 +149,9 @@ matrix:
|
||||||
- os: osx
|
- os: osx
|
||||||
osx_image: xcode10
|
osx_image: xcode10
|
||||||
|
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode10.1
|
||||||
|
|
||||||
# Linux / GCC
|
# Linux / GCC
|
||||||
|
|
||||||
- os: linux
|
- os: linux
|
||||||
|
@ -290,15 +278,23 @@ matrix:
|
||||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
|
||||||
packages: ['g++-6', 'clang-6.0', 'ninja-build']
|
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
|
- os: linux
|
||||||
compiler: clang
|
compiler: clang
|
||||||
env:
|
env:
|
||||||
- COMPILER=clang++-6.0
|
- COMPILER=clang++-7
|
||||||
- CXXFLAGS=-std=c++1z
|
- CXXFLAGS=-std=c++1z
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
|
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
|
||||||
packages: ['g++-6', 'clang-6.0', 'ninja-build']
|
packages: ['g++-6', 'clang-7', 'ninja-build']
|
||||||
|
|
||||||
################
|
################
|
||||||
# build script #
|
# build script #
|
||||||
|
|
|
@ -16,6 +16,7 @@ include(ExternalProject)
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
##
|
##
|
||||||
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
|
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)
|
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(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
|
||||||
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
|
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
|
||||||
|
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)
|
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
${NLOHMANN_JSON_TARGET_NAME}
|
${NLOHMANN_JSON_TARGET_NAME}
|
||||||
|
@ -92,6 +97,7 @@ configure_file(
|
||||||
@ONLY
|
@ONLY
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(JSON_Install)
|
||||||
install(
|
install(
|
||||||
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
|
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
|
||||||
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||||
|
@ -121,3 +127,4 @@ install(
|
||||||
NAMESPACE ${PROJECT_NAME}::
|
NAMESPACE ${PROJECT_NAME}::
|
||||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
210
Makefile
210
Makefile
|
@ -49,6 +49,9 @@ all:
|
||||||
@echo "clean - remove built files"
|
@echo "clean - remove built files"
|
||||||
@echo "coverage - create coverage information with lcov"
|
@echo "coverage - create coverage information with lcov"
|
||||||
@echo "cppcheck - analyze code with cppcheck"
|
@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 "doctest - compile example files and check their output"
|
||||||
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
|
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
|
||||||
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
|
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
|
||||||
|
@ -134,72 +137,233 @@ pedantic_clang:
|
||||||
-Wno-float-equal \
|
-Wno-float-equal \
|
||||||
-Wno-switch-enum -Wno-covered-switch-default \
|
-Wno-switch-enum -Wno-covered-switch-default \
|
||||||
-Wno-c++2a-compat \
|
-Wno-c++2a-compat \
|
||||||
|
-Wno-c++17-extensions \
|
||||||
-Wno-padded"
|
-Wno-padded"
|
||||||
|
|
||||||
# calling GCC with most warnings
|
# calling GCC with most warnings
|
||||||
pedantic_gcc:
|
pedantic_gcc:
|
||||||
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS=" \
|
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS=" \
|
||||||
-std=c++11 \
|
-std=c++11 \
|
||||||
-Wno-deprecated-declarations \
|
-Waddress \
|
||||||
-Werror \
|
-Waddress-of-packed-member \
|
||||||
-Wall -Wpedantic -Wextra \
|
-Waggressive-loop-optimizations \
|
||||||
|
-Waligned-new=all \
|
||||||
|
-Wall \
|
||||||
|
-Walloc-zero \
|
||||||
-Walloca \
|
-Walloca \
|
||||||
|
-Warray-bounds \
|
||||||
-Warray-bounds=2 \
|
-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 \
|
-Wchar-subscripts \
|
||||||
|
-Wclass-conversion \
|
||||||
|
-Wclass-memaccess \
|
||||||
|
-Wclobbered \
|
||||||
|
-Wcomment \
|
||||||
|
-Wcomments \
|
||||||
-Wconditionally-supported \
|
-Wconditionally-supported \
|
||||||
-Wconversion \
|
-Wconversion \
|
||||||
|
-Wconversion-null \
|
||||||
|
-Wcoverage-mismatch \
|
||||||
|
-Wcpp \
|
||||||
|
-Wctor-dtor-privacy \
|
||||||
|
-Wdangling-else \
|
||||||
-Wdate-time \
|
-Wdate-time \
|
||||||
|
-Wdelete-incomplete \
|
||||||
|
-Wdelete-non-virtual-dtor \
|
||||||
-Wdeprecated \
|
-Wdeprecated \
|
||||||
|
-Wdeprecated-copy \
|
||||||
|
-Wdeprecated-copy-dtor \
|
||||||
|
-Wdeprecated-declarations \
|
||||||
-Wdisabled-optimization \
|
-Wdisabled-optimization \
|
||||||
|
-Wdiv-by-zero \
|
||||||
-Wdouble-promotion \
|
-Wdouble-promotion \
|
||||||
-Wduplicated-branches \
|
-Wduplicated-branches \
|
||||||
-Wduplicated-cond \
|
-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-overflow=2 \
|
||||||
|
-Wformat-security \
|
||||||
-Wformat-signedness \
|
-Wformat-signedness \
|
||||||
-Wformat-truncation=2 \
|
-Wformat-truncation=2 \
|
||||||
|
-Wformat-y2k \
|
||||||
|
-Wformat-zero-length \
|
||||||
-Wformat=2 \
|
-Wformat=2 \
|
||||||
-Wno-ignored-qualifiers \
|
-Wframe-address \
|
||||||
|
-Wfree-nonheap-object \
|
||||||
|
-Whsa \
|
||||||
|
-Wif-not-aligned \
|
||||||
|
-Wignored-attributes \
|
||||||
|
-Wignored-qualifiers \
|
||||||
-Wimplicit-fallthrough=5 \
|
-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 \
|
-Wlogical-op \
|
||||||
|
-Wlto-type-mismatch \
|
||||||
|
-Wmain \
|
||||||
|
-Wmaybe-uninitialized \
|
||||||
|
-Wmemset-elt-size \
|
||||||
|
-Wmemset-transposed-args \
|
||||||
|
-Wmisleading-indentation \
|
||||||
|
-Wmissing-attributes \
|
||||||
|
-Wmissing-braces \
|
||||||
-Wmissing-declarations \
|
-Wmissing-declarations \
|
||||||
|
-Wmissing-field-initializers \
|
||||||
-Wmissing-format-attribute \
|
-Wmissing-format-attribute \
|
||||||
-Wmissing-include-dirs \
|
-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 \
|
||||||
|
-Wnoexcept-type \
|
||||||
|
-Wnon-template-friend \
|
||||||
|
-Wnon-virtual-dtor \
|
||||||
-Wnonnull \
|
-Wnonnull \
|
||||||
|
-Wnonnull-compare \
|
||||||
|
-Wnonportable-cfstrings \
|
||||||
|
-Wnormalized \
|
||||||
-Wnull-dereference \
|
-Wnull-dereference \
|
||||||
|
-Wodr \
|
||||||
-Wold-style-cast \
|
-Wold-style-cast \
|
||||||
|
-Wopenmp-simd \
|
||||||
|
-Woverflow \
|
||||||
|
-Woverlength-strings \
|
||||||
-Woverloaded-virtual \
|
-Woverloaded-virtual \
|
||||||
|
-Wpacked \
|
||||||
|
-Wpacked-bitfield-compat \
|
||||||
|
-Wpacked-not-aligned \
|
||||||
-Wparentheses \
|
-Wparentheses \
|
||||||
|
-Wpedantic \
|
||||||
|
-Wpessimizing-move \
|
||||||
-Wplacement-new=2 \
|
-Wplacement-new=2 \
|
||||||
|
-Wpmf-conversions \
|
||||||
|
-Wpointer-arith \
|
||||||
|
-Wpointer-compare \
|
||||||
|
-Wpragmas \
|
||||||
|
-Wprio-ctor-dtor \
|
||||||
|
-Wpsabi \
|
||||||
-Wredundant-decls \
|
-Wredundant-decls \
|
||||||
|
-Wredundant-move \
|
||||||
|
-Wregister \
|
||||||
-Wreorder \
|
-Wreorder \
|
||||||
-Wrestrict \
|
-Wrestrict \
|
||||||
|
-Wreturn-local-addr \
|
||||||
|
-Wreturn-type \
|
||||||
|
-Wscalar-storage-order \
|
||||||
|
-Wsequence-point \
|
||||||
|
-Wshadow \
|
||||||
|
-Wshadow-compatible-local \
|
||||||
|
-Wshadow-local \
|
||||||
|
-Wshadow=compatible-local \
|
||||||
-Wshadow=global \
|
-Wshadow=global \
|
||||||
|
-Wshadow=local \
|
||||||
|
-Wshift-count-negative \
|
||||||
|
-Wshift-count-overflow \
|
||||||
|
-Wshift-negative-value \
|
||||||
-Wshift-overflow=2 \
|
-Wshift-overflow=2 \
|
||||||
|
-Wsign-compare \
|
||||||
-Wsign-conversion \
|
-Wsign-conversion \
|
||||||
-Wsign-promo \
|
-Wsign-promo \
|
||||||
-Wsized-deallocation \
|
-Wsized-deallocation \
|
||||||
|
-Wsizeof-array-argument \
|
||||||
|
-Wsizeof-pointer-div \
|
||||||
|
-Wsizeof-pointer-memaccess \
|
||||||
|
-Wstack-protector \
|
||||||
|
-Wstrict-aliasing=3 \
|
||||||
|
-Wstrict-null-sentinel \
|
||||||
-Wstrict-overflow=5 \
|
-Wstrict-overflow=5 \
|
||||||
|
-Wstringop-overflow=4 \
|
||||||
|
-Wstringop-truncation \
|
||||||
|
-Wsubobject-linkage \
|
||||||
|
-Wsuggest-attribute=cold \
|
||||||
-Wsuggest-attribute=const \
|
-Wsuggest-attribute=const \
|
||||||
-Wsuggest-attribute=format \
|
-Wsuggest-attribute=format \
|
||||||
|
-Wsuggest-attribute=malloc \
|
||||||
-Wsuggest-attribute=noreturn \
|
-Wsuggest-attribute=noreturn \
|
||||||
-Wsuggest-attribute=pure \
|
-Wsuggest-attribute=pure \
|
||||||
-Wsuggest-final-methods \
|
-Wsuggest-final-methods \
|
||||||
-Wsuggest-final-types \
|
-Wsuggest-final-types \
|
||||||
-Wsuggest-override \
|
-Wsuggest-override \
|
||||||
|
-Wswitch \
|
||||||
|
-Wswitch-bool \
|
||||||
|
-Wswitch-default \
|
||||||
|
-Wswitch-unreachable \
|
||||||
|
-Wsync-nand \
|
||||||
|
-Wsynth \
|
||||||
|
-Wtautological-compare \
|
||||||
|
-Wterminate \
|
||||||
|
-Wtrampolines \
|
||||||
-Wtrigraphs \
|
-Wtrigraphs \
|
||||||
-Wundef \
|
-Wtype-limits \
|
||||||
-Wuninitialized -Wunknown-pragmas \
|
-Wuninitialized \
|
||||||
|
-Wunknown-pragmas \
|
||||||
|
-Wunreachable-code \
|
||||||
|
-Wunsafe-loop-optimizations \
|
||||||
-Wunused \
|
-Wunused \
|
||||||
|
-Wunused-but-set-parameter \
|
||||||
|
-Wunused-but-set-variable \
|
||||||
-Wunused-const-variable=2 \
|
-Wunused-const-variable=2 \
|
||||||
|
-Wunused-function \
|
||||||
|
-Wunused-label \
|
||||||
|
-Wunused-local-typedefs \
|
||||||
-Wunused-macros \
|
-Wunused-macros \
|
||||||
-Wunused-parameter \
|
-Wunused-parameter \
|
||||||
|
-Wunused-result \
|
||||||
|
-Wunused-value \
|
||||||
|
-Wunused-variable \
|
||||||
-Wuseless-cast \
|
-Wuseless-cast \
|
||||||
|
-Wvarargs \
|
||||||
-Wvariadic-macros \
|
-Wvariadic-macros \
|
||||||
-Wctor-dtor-privacy \
|
-Wvector-operation-performance \
|
||||||
-Winit-self \
|
-Wvirtual-inheritance \
|
||||||
-Wstrict-null-sentinel"
|
-Wvirtual-move-assign \
|
||||||
|
-Wvla \
|
||||||
|
-Wvolatile-register-var \
|
||||||
|
-Wwrite-strings \
|
||||||
|
-Wzero-as-null-pointer-constant \
|
||||||
|
"
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# benchmarks
|
# benchmarks
|
||||||
|
@ -276,7 +440,7 @@ fuzzing-stop:
|
||||||
|
|
||||||
# call cppcheck on the main header file
|
# call cppcheck on the main header file
|
||||||
cppcheck:
|
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
|
# compile and check with Clang Static Analyzer
|
||||||
clang_analyze:
|
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 ; 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
|
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
|
# maintainer targets
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
21
README.md
21
README.md
|
@ -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.
|
# run from your own project's code.
|
||||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
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
|
# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it
|
||||||
# unintended consequences that will break the build. It's generally
|
# unintended consequences that will break the build. It's generally
|
||||||
# discouraged (although not necessarily well documented as such) to use
|
# 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 [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.
|
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 [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
|
## 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)).
|
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;
|
})"_json;
|
||||||
|
|
||||||
// apply the patch
|
// apply the patch
|
||||||
j_original.merge_patch(j_patch);
|
j_document.merge_patch(j_patch);
|
||||||
// {
|
// {
|
||||||
// "a": "z",
|
// "a": "z",
|
||||||
// "c": {
|
// "c": {
|
||||||
|
@ -747,7 +753,7 @@ Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_jso
|
||||||
Some important things:
|
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 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.)
|
* 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.
|
* 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.
|
* 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_STOPPED, "stopped"},
|
||||||
{TS_RUNNING, "running"},
|
{TS_RUNNING, "running"},
|
||||||
{TS_COMPLETED, "completed"},
|
{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.
|
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 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 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 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 7.0.1 | Ubuntu 14.04.1 LTS | clang version 7.0.1-svn348686-1~exp1~20181213084532.54 (branches/release_70) |
|
||||||
| 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 Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) |
|
| 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.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.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.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 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.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 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 |
|
| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 |
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
cmake_minimum_required(VERSION 3.1)
|
cmake_minimum_required(VERSION 3.8)
|
||||||
project(JSON_Benchmarks LANGUAGES CXX)
|
project(JSON_Benchmarks LANGUAGES CXX)
|
||||||
|
|
||||||
# set compiler flags
|
# set compiler flags
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Doxyfile 1.8.15
|
# Doxyfile 1.8.16
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Project related configuration options
|
# Project related configuration options
|
||||||
|
@ -38,6 +38,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
|
||||||
OPTIMIZE_OUTPUT_JAVA = NO
|
OPTIMIZE_OUTPUT_JAVA = NO
|
||||||
OPTIMIZE_FOR_FORTRAN = NO
|
OPTIMIZE_FOR_FORTRAN = NO
|
||||||
OPTIMIZE_OUTPUT_VHDL = NO
|
OPTIMIZE_OUTPUT_VHDL = NO
|
||||||
|
OPTIMIZE_OUTPUT_SLICE = NO
|
||||||
EXTENSION_MAPPING =
|
EXTENSION_MAPPING =
|
||||||
MARKDOWN_SUPPORT = YES
|
MARKDOWN_SUPPORT = YES
|
||||||
TOC_INCLUDE_HEADINGS = 0
|
TOC_INCLUDE_HEADINGS = 0
|
||||||
|
@ -141,7 +142,7 @@ USE_HTAGS = NO
|
||||||
VERBATIM_HEADERS = NO
|
VERBATIM_HEADERS = NO
|
||||||
CLANG_ASSISTED_PARSING = YES
|
CLANG_ASSISTED_PARSING = YES
|
||||||
CLANG_OPTIONS = -std=c++11
|
CLANG_OPTIONS = -std=c++11
|
||||||
CLANG_COMPILATION_DATABASE_PATH = 0
|
CLANG_DATABASE_PATH =
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the alphabetical class index
|
# Configuration options related to the alphabetical class index
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
@ -214,6 +215,7 @@ GENERATE_LATEX = NO
|
||||||
LATEX_OUTPUT = latex
|
LATEX_OUTPUT = latex
|
||||||
LATEX_CMD_NAME = latex
|
LATEX_CMD_NAME = latex
|
||||||
MAKEINDEX_CMD_NAME = makeindex
|
MAKEINDEX_CMD_NAME = makeindex
|
||||||
|
LATEX_MAKEINDEX_CMD = \makeindex
|
||||||
COMPACT_LATEX = NO
|
COMPACT_LATEX = NO
|
||||||
PAPER_TYPE = a4
|
PAPER_TYPE = a4
|
||||||
EXTRA_PACKAGES =
|
EXTRA_PACKAGES =
|
||||||
|
@ -228,6 +230,7 @@ LATEX_HIDE_INDICES = NO
|
||||||
LATEX_SOURCE_CODE = NO
|
LATEX_SOURCE_CODE = NO
|
||||||
LATEX_BIB_STYLE = plain
|
LATEX_BIB_STYLE = plain
|
||||||
LATEX_TIMESTAMP = NO
|
LATEX_TIMESTAMP = NO
|
||||||
|
LATEX_EMOJI_DIRECTORY =
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the RTF output
|
# Configuration options related to the RTF output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
@ -252,6 +255,7 @@ MAN_LINKS = NO
|
||||||
GENERATE_XML = YES
|
GENERATE_XML = YES
|
||||||
XML_OUTPUT = xml
|
XML_OUTPUT = xml
|
||||||
XML_PROGRAMLISTING = YES
|
XML_PROGRAMLISTING = YES
|
||||||
|
XML_NS_MEMB_FILE_SCOPE = NO
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Configuration options related to the DOCBOOK output
|
# Configuration options related to the DOCBOOK output
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
|
|
17
doc/examples/contains.cpp
Normal file
17
doc/examples/contains.cpp
Normal 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;
|
||||||
|
}
|
1
doc/examples/contains.link
Normal file
1
doc/examples/contains.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="https://wandbox.org/permlink/iHSlXjtjhgO9Q1Tw"><b>online</b></a>
|
3
doc/examples/contains.output
Normal file
3
doc/examples/contains.output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
j_object contains 'key': true
|
||||||
|
j_object contains 'another': false
|
||||||
|
j_array contains 'key': false
|
20
doc/examples/json_pointer__empty.cpp
Normal file
20
doc/examples/json_pointer__empty.cpp
Normal 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;
|
||||||
|
}
|
1
doc/examples/json_pointer__empty.link
Normal file
1
doc/examples/json_pointer__empty.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="https://wandbox.org/permlink/pqG2Q8bmj9SvSX0i"><b>online</b></a>
|
4
doc/examples/json_pointer__empty.output
Normal file
4
doc/examples/json_pointer__empty.output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
"": true
|
||||||
|
"": true
|
||||||
|
"/foo": false
|
||||||
|
"/foo/0": false
|
18
doc/examples/json_pointer__parent_pointer.cpp
Normal file
18
doc/examples/json_pointer__parent_pointer.cpp
Normal 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;
|
||||||
|
}
|
1
doc/examples/json_pointer__parent_pointer.link
Normal file
1
doc/examples/json_pointer__parent_pointer.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="https://wandbox.org/permlink/yweqBQ8bAC6pcn68"><b>online</b></a>
|
3
doc/examples/json_pointer__parent_pointer.output
Normal file
3
doc/examples/json_pointer__parent_pointer.output
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
parent of "" is ""
|
||||||
|
parent of "/foo" is ""
|
||||||
|
parent of "/foo/0" is "/foo"
|
21
doc/examples/json_pointer__push_back.cpp
Normal file
21
doc/examples/json_pointer__push_back.cpp
Normal 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';
|
||||||
|
}
|
1
doc/examples/json_pointer__push_back.link
Normal file
1
doc/examples/json_pointer__push_back.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="https://wandbox.org/permlink/kLC7IUvqQ6XJCeG9"><b>online</b></a>
|
4
doc/examples/json_pointer__push_back.output
Normal file
4
doc/examples/json_pointer__push_back.output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
""
|
||||||
|
"/foo"
|
||||||
|
"/foo/0"
|
||||||
|
"/foo/0/bar"
|
|
@ -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_integer_t signed integers @endlink
|
||||||
- @link nlohmann::basic_json::number_unsigned_t unsigned integers @endlink
|
- @link nlohmann::basic_json::number_unsigned_t unsigned integers @endlink
|
||||||
- @link nlohmann::basic_json::number_float_t floating-point @endlink
|
- @link nlohmann::basic_json::number_float_t floating-point @endlink
|
||||||
|
- @link nlohmann::json_pointer JSON Pointer @endlink
|
||||||
|
|
||||||
# Container function overview
|
# Container function overview
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array> // array
|
||||||
#include <cassert> // assert
|
#include <cassert> // assert
|
||||||
#include <ciso646> // or, and, not
|
#include <ciso646> // or, and, not
|
||||||
#include <cmath> // signbit, isfinite
|
#include <cmath> // signbit, isfinite
|
||||||
|
@ -49,10 +50,10 @@ struct diyfp // f * 2^e
|
||||||
{
|
{
|
||||||
static constexpr int kPrecision = 64; // = q
|
static constexpr int kPrecision = 64; // = q
|
||||||
|
|
||||||
uint64_t f = 0;
|
std::uint64_t f = 0;
|
||||||
int e = 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
|
@brief returns x - y
|
||||||
|
@ -97,23 +98,23 @@ struct diyfp // f * 2^e
|
||||||
//
|
//
|
||||||
// = p_lo + 2^64 p_hi
|
// = p_lo + 2^64 p_hi
|
||||||
|
|
||||||
const uint64_t u_lo = x.f & 0xFFFFFFFF;
|
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
|
||||||
const uint64_t u_hi = x.f >> 32;
|
const std::uint64_t u_hi = x.f >> 32u;
|
||||||
const uint64_t v_lo = y.f & 0xFFFFFFFF;
|
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
|
||||||
const uint64_t v_hi = y.f >> 32;
|
const std::uint64_t v_hi = y.f >> 32u;
|
||||||
|
|
||||||
const uint64_t p0 = u_lo * v_lo;
|
const std::uint64_t p0 = u_lo * v_lo;
|
||||||
const uint64_t p1 = u_lo * v_hi;
|
const std::uint64_t p1 = u_lo * v_hi;
|
||||||
const uint64_t p2 = u_hi * v_lo;
|
const std::uint64_t p2 = u_hi * v_lo;
|
||||||
const uint64_t p3 = u_hi * v_hi;
|
const std::uint64_t p3 = u_hi * v_hi;
|
||||||
|
|
||||||
const uint64_t p0_hi = p0 >> 32;
|
const std::uint64_t p0_hi = p0 >> 32u;
|
||||||
const uint64_t p1_lo = p1 & 0xFFFFFFFF;
|
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
|
||||||
const uint64_t p1_hi = p1 >> 32;
|
const std::uint64_t p1_hi = p1 >> 32u;
|
||||||
const uint64_t p2_lo = p2 & 0xFFFFFFFF;
|
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
|
||||||
const uint64_t p2_hi = p2 >> 32;
|
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
|
// 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
|
// Effectively we only need to add the highest bit in p_lo to p_hi (and
|
||||||
// Q_hi + 1 does not overflow).
|
// 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};
|
return {h, x.e + y.e + 64};
|
||||||
}
|
}
|
||||||
|
@ -139,9 +140,9 @@ struct diyfp // f * 2^e
|
||||||
{
|
{
|
||||||
assert(x.f != 0);
|
assert(x.f != 0);
|
||||||
|
|
||||||
while ((x.f >> 63) == 0)
|
while ((x.f >> 63u) == 0)
|
||||||
{
|
{
|
||||||
x.f <<= 1;
|
x.f <<= 1u;
|
||||||
x.e--;
|
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 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 kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
|
||||||
constexpr int kMinExp = 1 - kBias;
|
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 std::uint64_t bits = reinterpret_bits<bits_type>(value);
|
||||||
const uint64_t E = bits >> (kPrecision - 1);
|
const std::uint64_t E = bits >> (kPrecision - 1);
|
||||||
const uint64_t F = bits & (kHiddenBit - 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
|
const diyfp v = is_denormal
|
||||||
? diyfp(F, kMinExp)
|
? diyfp(F, kMinExp)
|
||||||
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
|
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
|
||||||
|
@ -229,7 +230,7 @@ boundaries compute_boundaries(FloatType value)
|
||||||
// -----------------+------+------+-------------+-------------+--- (B)
|
// -----------------+------+------+-------------+-------------+--- (B)
|
||||||
// v- m- v m+ v+
|
// 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_plus = diyfp(2 * v.f + 1, v.e - 1);
|
||||||
const diyfp m_minus = lower_boundary_is_closer
|
const diyfp m_minus = lower_boundary_is_closer
|
||||||
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
? 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
|
struct cached_power // c = f * 2^e ~= 10^k
|
||||||
{
|
{
|
||||||
uint64_t f;
|
std::uint64_t f;
|
||||||
int e;
|
int e;
|
||||||
int k;
|
int k;
|
||||||
};
|
};
|
||||||
|
@ -368,11 +369,11 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
||||||
// NB:
|
// NB:
|
||||||
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
|
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
|
||||||
|
|
||||||
constexpr int kCachedPowersSize = 79;
|
|
||||||
constexpr int kCachedPowersMinDecExp = -300;
|
constexpr int kCachedPowersMinDecExp = -300;
|
||||||
constexpr int kCachedPowersDecStep = 8;
|
constexpr int kCachedPowersDecStep = 8;
|
||||||
|
|
||||||
static constexpr cached_power kCachedPowers[] =
|
static constexpr std::array<cached_power, 79> kCachedPowers =
|
||||||
|
{
|
||||||
{
|
{
|
||||||
{ 0xAB70FE17C79AC6CA, -1060, -300 },
|
{ 0xAB70FE17C79AC6CA, -1060, -300 },
|
||||||
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
|
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
|
||||||
|
@ -453,6 +454,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
||||||
{ 0x8E679C2F5E44FF8F, 960, 308 },
|
{ 0x8E679C2F5E44FF8F, 960, 308 },
|
||||||
{ 0xD433179D9C8CB841, 986, 316 },
|
{ 0xD433179D9C8CB841, 986, 316 },
|
||||||
{ 0x9E19DB92B4E31BA9, 1013, 324 },
|
{ 0x9E19DB92B4E31BA9, 1013, 324 },
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This computation gives exactly the same results for k as
|
// 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;
|
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
|
||||||
assert(index >= 0);
|
assert(index >= 0);
|
||||||
assert(index < kCachedPowersSize);
|
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
|
||||||
static_cast<void>(kCachedPowersSize); // Fix warning.
|
|
||||||
|
|
||||||
const cached_power cached = kCachedPowers[index];
|
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
|
||||||
assert(kAlpha <= cached.e + e + 64);
|
assert(kAlpha <= cached.e + e + 64);
|
||||||
assert(kGamma >= 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 k, such that pow10 := 10^(k-1) <= n < 10^k.
|
||||||
For n == 0, returns 1 and sets pow10 := 1.
|
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
|
// LCOV_EXCL_START
|
||||||
if (n >= 1000000000)
|
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,
|
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
||||||
uint64_t rest, uint64_t ten_k)
|
std::uint64_t rest, std::uint64_t ten_k)
|
||||||
{
|
{
|
||||||
assert(len >= 1);
|
assert(len >= 1);
|
||||||
assert(dist <= delta);
|
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 >= kAlpha);
|
||||||
assert(M_plus.e <= kGamma);
|
assert(M_plus.e <= kGamma);
|
||||||
|
|
||||||
uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
std::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 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):
|
// 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 ) * 2^-e + (p2 )) * 2^e
|
||||||
// = p1 + 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.)
|
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.)
|
||||||
uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
||||||
|
|
||||||
// 1)
|
// 1)
|
||||||
//
|
//
|
||||||
|
@ -619,7 +620,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
||||||
|
|
||||||
assert(p1 > 0);
|
assert(p1 > 0);
|
||||||
|
|
||||||
uint32_t pow10;
|
std::uint32_t pow10;
|
||||||
const int k = find_largest_pow10(p1, pow10);
|
const int k = find_largest_pow10(p1, pow10);
|
||||||
|
|
||||||
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
|
// 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)
|
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
|
||||||
// pow10 = 10^(n-1) <= p1 < 10^n
|
// pow10 = 10^(n-1) <= p1 < 10^n
|
||||||
//
|
//
|
||||||
const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
|
const std::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 r = p1 % pow10; // r = p1 mod 10^(n-1)
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
||||||
// = (buffer * 10 + 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:
|
// Note:
|
||||||
// Since rest and delta share the same exponent e, it suffices to
|
// Since rest and delta share the same exponent e, it suffices to
|
||||||
// compare the significands.
|
// 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)
|
if (rest <= delta)
|
||||||
{
|
{
|
||||||
// V = buffer * 10^n, with M- <= V <= M+.
|
// 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
|
// 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);
|
grisu2_round(buffer, length, dist, delta, rest, ten_n);
|
||||||
|
|
||||||
return;
|
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) ) * 2^e
|
||||||
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 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;
|
p2 *= 10;
|
||||||
const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
const std::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 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
|
// 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))
|
// = 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
|
// 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);
|
grisu2_round(buffer, length, dist, delta, p2, ten_m);
|
||||||
|
|
||||||
// By construction this algorithm generates the shortest possible decimal
|
// By construction this algorithm generates the shortest possible decimal
|
||||||
|
@ -929,7 +930,7 @@ inline char* append_exponent(char* buf, int e)
|
||||||
*buf++ = '+';
|
*buf++ = '+';
|
||||||
}
|
}
|
||||||
|
|
||||||
auto k = static_cast<uint32_t>(e);
|
auto k = static_cast<std::uint32_t>(e);
|
||||||
if (k < 10)
|
if (k < 10)
|
||||||
{
|
{
|
||||||
// Always print at least two digits in the exponent.
|
// Always print at least two digits in the exponent.
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm> // copy
|
||||||
#include <ciso646> // or, and, not
|
#include <ciso646> // or, and, not
|
||||||
#include <iterator> // begin, end
|
#include <iterator> // begin, end
|
||||||
|
#include <string> // string
|
||||||
#include <tuple> // tuple, get
|
#include <tuple> // tuple, get
|
||||||
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
|
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
|
||||||
#include <utility> // move, forward, declval, pair
|
#include <utility> // move, forward, declval, pair
|
||||||
#include <valarray> // valarray
|
#include <valarray> // valarray
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
|
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
@liveexample{The following code shows how a `parse_error` exception can be
|
||||||
caught.,parse_error}
|
caught.,parse_error}
|
||||||
|
|
||||||
@sa @ref exception for the base class of the library exceptions
|
@sa - @ref exception for the base class of the library exceptions
|
||||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||||
@sa @ref type_error for exceptions indicating executing a member function with
|
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||||
a wrong type
|
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
|
||||||
@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
|
@since version 3.0.0
|
||||||
*/
|
*/
|
||||||
|
@ -117,7 +117,7 @@ class parse_error : public exception
|
||||||
/*!
|
/*!
|
||||||
@brief create a parse error exception
|
@brief create a parse error exception
|
||||||
@param[in] id_ the id of the 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
|
chars_read_total=0 if the position cannot be
|
||||||
determined)
|
determined)
|
||||||
@param[in] what_arg the explanatory string
|
@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
|
@liveexample{The following code shows how an `invalid_iterator` exception can be
|
||||||
caught.,invalid_iterator}
|
caught.,invalid_iterator}
|
||||||
|
|
||||||
@sa @ref exception for the base class of the library exceptions
|
@sa - @ref exception for the base class of the library exceptions
|
||||||
@sa @ref parse_error for exceptions indicating a parse error
|
@sa - @ref parse_error for exceptions indicating a parse error
|
||||||
@sa @ref type_error for exceptions indicating executing a member function with
|
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||||
a wrong type
|
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
|
||||||
@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
|
@since version 3.0.0
|
||||||
*/
|
*/
|
||||||
|
@ -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
|
@liveexample{The following code shows how a `type_error` exception can be
|
||||||
caught.,type_error}
|
caught.,type_error}
|
||||||
|
|
||||||
@sa @ref exception for the base class of the library exceptions
|
@sa - @ref exception for the base class of the library exceptions
|
||||||
@sa @ref parse_error for exceptions indicating a parse error
|
@sa - @ref parse_error for exceptions indicating a parse error
|
||||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
@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 out_of_range for exceptions indicating access out of the defined range
|
||||||
@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
|
@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
|
@liveexample{The following code shows how an `out_of_range` exception can be
|
||||||
caught.,out_of_range}
|
caught.,out_of_range}
|
||||||
|
|
||||||
@sa @ref exception for the base class of the library exceptions
|
@sa - @ref exception for the base class of the library exceptions
|
||||||
@sa @ref parse_error for exceptions indicating a parse error
|
@sa - @ref parse_error for exceptions indicating a parse error
|
||||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||||
@sa @ref type_error for exceptions indicating executing a member function with
|
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||||
a wrong type
|
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
|
@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.
|
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 exception for the base class of the library exceptions
|
||||||
@sa @ref parse_error for exceptions indicating a parse error
|
@sa - @ref parse_error for exceptions indicating a parse error
|
||||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||||
@sa @ref type_error for exceptions indicating executing a member function with
|
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||||
a wrong type
|
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
|
@liveexample{The following code shows how an `other_error` exception can be
|
||||||
caught.,other_error}
|
caught.,other_error}
|
||||||
|
|
|
@ -13,9 +13,9 @@
|
||||||
#include <string> // char_traits, string
|
#include <string> // char_traits, string
|
||||||
#include <utility> // make_pair, move
|
#include <utility> // make_pair, move
|
||||||
|
|
||||||
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/json_sax.hpp>
|
#include <nlohmann/detail/input/json_sax.hpp>
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/is_sax.hpp>
|
#include <nlohmann/detail/meta/is_sax.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
@ -52,6 +52,13 @@ class binary_reader
|
||||||
assert(ia);
|
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] format the binary format to parse
|
||||||
@param[in] sax_ a SAX event processor
|
@param[in] sax_ a SAX event processor
|
||||||
|
@ -84,10 +91,8 @@ class binary_reader
|
||||||
result = parse_ubjson_internal();
|
result = parse_ubjson_internal();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
default: // LCOV_EXCL_LINE
|
||||||
default:
|
assert(false); // LCOV_EXCL_LINE
|
||||||
assert(false);
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// strict mode: next byte must be EOF
|
// strict mode: next byte must be EOF
|
||||||
|
@ -121,7 +126,7 @@ class binary_reader
|
||||||
*/
|
*/
|
||||||
static constexpr bool little_endianess(int num = 1) noexcept
|
static constexpr bool little_endianess(int num = 1) noexcept
|
||||||
{
|
{
|
||||||
return (*reinterpret_cast<char*>(&num) == 1);
|
return *reinterpret_cast<char*>(&num) == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -263,9 +268,9 @@ class binary_reader
|
||||||
|
|
||||||
default: // anything else not supported (yet)
|
default: // anything else not supported (yet)
|
||||||
{
|
{
|
||||||
char cr[3];
|
std::array<char, 3> cr{};
|
||||||
(std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
|
(std::snprintf)(cr.data(), cr.size(), "%.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)));
|
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,13 +303,10 @@ class binary_reader
|
||||||
return false;
|
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)))
|
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)
|
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);
|
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x19: // Unsigned integer (two-byte uint16_t follows)
|
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);
|
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
|
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);
|
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
|
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);
|
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,29 +437,29 @@ class binary_reader
|
||||||
case 0x35:
|
case 0x35:
|
||||||
case 0x36:
|
case 0x36:
|
||||||
case 0x37:
|
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)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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)
|
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)
|
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
|
||||||
- static_cast<number_integer_t>(number));
|
- static_cast<number_integer_t>(number));
|
||||||
}
|
}
|
||||||
|
@ -522,29 +524,29 @@ class binary_reader
|
||||||
case 0x95:
|
case 0x95:
|
||||||
case 0x96:
|
case 0x96:
|
||||||
case 0x97:
|
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)
|
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));
|
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)
|
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));
|
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)
|
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));
|
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)
|
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));
|
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 0xB5:
|
||||||
case 0xB6:
|
case 0xB6:
|
||||||
case 0xB7:
|
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)
|
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));
|
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)
|
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));
|
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)
|
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));
|
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)
|
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));
|
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
|
// without such support. An example of a small decoder for
|
||||||
// half-precision floating-point numbers in the C language
|
// half-precision floating-point numbers in the C language
|
||||||
// is shown in Fig. 3.
|
// 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 double val = [&half]
|
||||||
{
|
{
|
||||||
const int exp = (half >> 10) & 0x1F;
|
const int exp = (half >> 10u) & 0x1Fu;
|
||||||
const int mant = half & 0x3FF;
|
const unsigned int mant = half & 0x3FFu;
|
||||||
assert(0 <= exp and exp <= 32);
|
assert(0 <= exp and exp <= 32);
|
||||||
assert(0 <= mant and mant <= 1024);
|
assert(0 <= mant and mant <= 1024);
|
||||||
switch (exp)
|
switch (exp)
|
||||||
|
@ -657,7 +659,7 @@ class binary_reader
|
||||||
return std::ldexp(mant + 1024, exp - 25);
|
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)
|
||||||
: static_cast<number_float_t>(val), "");
|
: static_cast<number_float_t>(val), "");
|
||||||
}
|
}
|
||||||
|
@ -728,30 +730,30 @@ class binary_reader
|
||||||
case 0x76:
|
case 0x76:
|
||||||
case 0x77:
|
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)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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)
|
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);
|
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 0x8D:
|
||||||
case 0x8E:
|
case 0x8E:
|
||||||
case 0x8F:
|
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
|
// fixarray
|
||||||
case 0x90:
|
case 0x90:
|
||||||
|
@ -1045,7 +1047,7 @@ class binary_reader
|
||||||
case 0x9D:
|
case 0x9D:
|
||||||
case 0x9E:
|
case 0x9E:
|
||||||
case 0x9F:
|
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
|
// fixstr
|
||||||
case 0xA0:
|
case 0xA0:
|
||||||
|
@ -1108,49 +1110,49 @@ class binary_reader
|
||||||
|
|
||||||
case 0xCC: // uint 8
|
case 0xCC: // uint 8
|
||||||
{
|
{
|
||||||
uint8_t number;
|
std::uint8_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xCD: // uint 16
|
case 0xCD: // uint 16
|
||||||
{
|
{
|
||||||
uint16_t number;
|
std::uint16_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xCE: // uint 32
|
case 0xCE: // uint 32
|
||||||
{
|
{
|
||||||
uint32_t number;
|
std::uint32_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xCF: // uint 64
|
case 0xCF: // uint 64
|
||||||
{
|
{
|
||||||
uint64_t number;
|
std::uint64_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xD0: // int 8
|
case 0xD0: // int 8
|
||||||
{
|
{
|
||||||
int8_t number;
|
std::int8_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xD1: // int 16
|
case 0xD1: // int 16
|
||||||
{
|
{
|
||||||
int16_t number;
|
std::int16_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xD2: // int 32
|
case 0xD2: // int 32
|
||||||
{
|
{
|
||||||
int32_t number;
|
std::int32_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xD3: // int 64
|
case 0xD3: // int 64
|
||||||
{
|
{
|
||||||
int64_t number;
|
std::int64_t number;
|
||||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(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
|
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));
|
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xDD: // array 32
|
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));
|
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xDE: // map 16
|
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));
|
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xDF: // map 32
|
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));
|
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 0xFD:
|
||||||
case 0xFE:
|
case 0xFE:
|
||||||
case 0xFF:
|
case 0xFF:
|
||||||
return sax->number_integer(static_cast<int8_t>(current));
|
return sax->number_integer(static_cast<std::int8_t>(current));
|
||||||
|
|
||||||
default: // anything else
|
default: // anything else
|
||||||
{
|
{
|
||||||
|
@ -1282,24 +1284,24 @@ class binary_reader
|
||||||
case 0xBE:
|
case 0xBE:
|
||||||
case 0xBF:
|
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
|
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);
|
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xDA: // str 16
|
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);
|
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0xDB: // str 32
|
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);
|
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)
|
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")))
|
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
|
||||||
|
@ -1409,31 +1411,31 @@ class binary_reader
|
||||||
{
|
{
|
||||||
case 'U':
|
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);
|
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'i':
|
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);
|
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'I':
|
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);
|
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'l':
|
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);
|
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'L':
|
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);
|
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':
|
case 'U':
|
||||||
{
|
{
|
||||||
uint8_t number;
|
std::uint8_t number;
|
||||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1464,7 +1466,7 @@ class binary_reader
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
{
|
{
|
||||||
int8_t number;
|
std::int8_t number;
|
||||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1475,7 +1477,7 @@ class binary_reader
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
{
|
{
|
||||||
int16_t number;
|
std::int16_t number;
|
||||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1486,7 +1488,7 @@ class binary_reader
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
{
|
{
|
||||||
int32_t number;
|
std::int32_t number;
|
||||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1497,7 +1499,7 @@ class binary_reader
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
{
|
{
|
||||||
int64_t number;
|
std::int64_t number;
|
||||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -1552,10 +1554,12 @@ class binary_reader
|
||||||
|
|
||||||
return get_ubjson_size_value(result.first);
|
return get_ubjson_size_value(result.first);
|
||||||
}
|
}
|
||||||
else if (current == '#')
|
|
||||||
|
if (current == '#')
|
||||||
{
|
{
|
||||||
return get_ubjson_size_value(result.first);
|
return get_ubjson_size_value(result.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1580,31 +1584,31 @@ class binary_reader
|
||||||
|
|
||||||
case 'U':
|
case 'U':
|
||||||
{
|
{
|
||||||
uint8_t number;
|
std::uint8_t number;
|
||||||
return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
|
return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'i':
|
case 'i':
|
||||||
{
|
{
|
||||||
int8_t number;
|
std::int8_t number;
|
||||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'I':
|
case 'I':
|
||||||
{
|
{
|
||||||
int16_t number;
|
std::int16_t number;
|
||||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
{
|
{
|
||||||
int32_t number;
|
std::int32_t number;
|
||||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
{
|
{
|
||||||
int64_t number;
|
std::int64_t number;
|
||||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1809,7 +1813,7 @@ class binary_reader
|
||||||
int get()
|
int get()
|
||||||
{
|
{
|
||||||
++chars_read;
|
++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)
|
bool get_number(const input_format_t format, NumberType& result)
|
||||||
{
|
{
|
||||||
// step 1: read input into array with system's byte order
|
// 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)
|
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
|
@ -1853,13 +1857,13 @@ class binary_reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// reverse byte order prior to conversion if necessary
|
// 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
|
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
|
std::string get_token_string() const
|
||||||
{
|
{
|
||||||
char cr[3];
|
std::array<char, 3> cr{};
|
||||||
(std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
|
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
|
||||||
return std::string{cr};
|
return std::string{cr.data()};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1955,10 +1959,8 @@ class binary_reader
|
||||||
error_msg += "BSON";
|
error_msg += "BSON";
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
default: // LCOV_EXCL_LINE
|
||||||
default:
|
assert(false); // LCOV_EXCL_LINE
|
||||||
assert(false);
|
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return error_msg + " " + context + ": " + detail;
|
return error_msg + " " + context + ": " + detail;
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array> // array
|
||||||
#include <cassert> // assert
|
#include <cassert> // assert
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
#include <cstdio> //FILE *
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
#include <istream> // istream
|
#include <istream> // istream
|
||||||
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
||||||
|
@ -10,7 +12,6 @@
|
||||||
#include <string> // string, char_traits
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
||||||
#include <utility> // pair, declval
|
#include <utility> // pair, declval
|
||||||
#include <cstdio> //FILE *
|
|
||||||
|
|
||||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
@ -58,10 +59,18 @@ class file_input_adapter : public input_adapter_protocol
|
||||||
: m_file(f)
|
: 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
|
std::char_traits<char>::int_type get_character() noexcept override
|
||||||
{
|
{
|
||||||
return std::fgetc(m_file);
|
return std::fgetc(m_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the file pointer to read from
|
/// the file pointer to read from
|
||||||
std::FILE* m_file;
|
std::FILE* m_file;
|
||||||
|
@ -153,7 +162,11 @@ template<typename WideStringType, size_t T>
|
||||||
struct wide_string_input_helper
|
struct wide_string_input_helper
|
||||||
{
|
{
|
||||||
// UTF-32
|
// 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;
|
utf8_bytes_index = 0;
|
||||||
|
|
||||||
|
@ -165,39 +178,39 @@ struct wide_string_input_helper
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get the current character
|
// 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
|
// UTF-32 to UTF-8 encoding
|
||||||
if (wc < 0x80)
|
if (wc < 0x80)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = wc;
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||||
utf8_bytes_filled = 1;
|
utf8_bytes_filled = 1;
|
||||||
}
|
}
|
||||||
else if (wc <= 0x7FF)
|
else if (wc <= 0x7FF)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
|
||||||
utf8_bytes[1] = 0x80 | (wc & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||||
utf8_bytes_filled = 2;
|
utf8_bytes_filled = 2;
|
||||||
}
|
}
|
||||||
else if (wc <= 0xFFFF)
|
else if (wc <= 0xFFFF)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
|
||||||
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||||
utf8_bytes[2] = 0x80 | (wc & 0x3F);
|
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||||
utf8_bytes_filled = 3;
|
utf8_bytes_filled = 3;
|
||||||
}
|
}
|
||||||
else if (wc <= 0x10FFFF)
|
else if (wc <= 0x10FFFF)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
|
||||||
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
|
||||||
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
|
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||||
utf8_bytes[3] = 0x80 | (wc & 0x3F);
|
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||||
utf8_bytes_filled = 4;
|
utf8_bytes_filled = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// unknown character
|
// unknown character
|
||||||
utf8_bytes[0] = wc;
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||||
utf8_bytes_filled = 1;
|
utf8_bytes_filled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,7 +221,11 @@ template<typename WideStringType>
|
||||||
struct wide_string_input_helper<WideStringType, 2>
|
struct wide_string_input_helper<WideStringType, 2>
|
||||||
{
|
{
|
||||||
// UTF-16
|
// 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;
|
utf8_bytes_index = 0;
|
||||||
|
|
||||||
|
@ -220,44 +237,44 @@ struct wide_string_input_helper<WideStringType, 2>
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// get the current character
|
// 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
|
// UTF-16 to UTF-8 encoding
|
||||||
if (wc < 0x80)
|
if (wc < 0x80)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = wc;
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||||
utf8_bytes_filled = 1;
|
utf8_bytes_filled = 1;
|
||||||
}
|
}
|
||||||
else if (wc <= 0x7FF)
|
else if (wc <= 0x7FF)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = 0xC0 | ((wc >> 6));
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
|
||||||
utf8_bytes[1] = 0x80 | (wc & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||||
utf8_bytes_filled = 2;
|
utf8_bytes_filled = 2;
|
||||||
}
|
}
|
||||||
else if (0xD800 > wc or wc >= 0xE000)
|
else if (0xD800 > wc or wc >= 0xE000)
|
||||||
{
|
{
|
||||||
utf8_bytes[0] = 0xE0 | ((wc >> 12));
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
|
||||||
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||||
utf8_bytes[2] = 0x80 | (wc & 0x3F);
|
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||||
utf8_bytes_filled = 3;
|
utf8_bytes_filled = 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (current_wchar < str.size())
|
if (current_wchar < str.size())
|
||||||
{
|
{
|
||||||
const auto wc2 = static_cast<int>(str[current_wchar++]);
|
const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
|
||||||
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
|
const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||||
utf8_bytes[0] = 0xf0 | (charcode >> 18);
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
|
||||||
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
|
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
|
||||||
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
|
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
|
||||||
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
|
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
|
||||||
utf8_bytes_filled = 4;
|
utf8_bytes_filled = 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// unknown character
|
// unknown character
|
||||||
++current_wchar;
|
++current_wchar;
|
||||||
utf8_bytes[0] = wc;
|
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||||
utf8_bytes_filled = 1;
|
utf8_bytes_filled = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert> // assert
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string>
|
#include <string> // string
|
||||||
#include <vector>
|
#include <utility> // move
|
||||||
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
@ -158,6 +159,13 @@ class json_sax_dom_parser
|
||||||
: root(r), allow_exceptions(allow_exceptions_)
|
: 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()
|
bool null()
|
||||||
{
|
{
|
||||||
handle_value(nullptr);
|
handle_value(nullptr);
|
||||||
|
@ -249,16 +257,16 @@ class json_sax_dom_parser
|
||||||
switch ((ex.id / 100) % 100)
|
switch ((ex.id / 100) % 100)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||||
case 4:
|
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
|
// LCOV_EXCL_START
|
||||||
case 2:
|
case 2:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||||
case 3:
|
case 3:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||||
case 5:
|
case 5:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
@ -295,18 +303,17 @@ class json_sax_dom_parser
|
||||||
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
|
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
|
||||||
return &(ref_stack.back()->m_value.array->back());
|
return &(ref_stack.back()->m_value.array->back());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
assert(ref_stack.back()->is_object())
|
||||||
assert(object_element);
|
assert(object_element);
|
||||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||||
return object_element;
|
return object_element;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// 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
|
/// helper to hold the reference for the next object element
|
||||||
BasicJsonType* object_element = nullptr;
|
BasicJsonType* object_element = nullptr;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
|
@ -334,6 +341,13 @@ class json_sax_dom_callback_parser
|
||||||
keep_stack.push_back(true);
|
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()
|
bool null()
|
||||||
{
|
{
|
||||||
handle_value(nullptr);
|
handle_value(nullptr);
|
||||||
|
@ -380,13 +394,9 @@ class json_sax_dom_callback_parser
|
||||||
ref_stack.push_back(val.second);
|
ref_stack.push_back(val.second);
|
||||||
|
|
||||||
// check object limit
|
// 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;
|
return true;
|
||||||
|
@ -411,25 +421,20 @@ class json_sax_dom_callback_parser
|
||||||
|
|
||||||
bool end_object()
|
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
|
// discard object
|
||||||
*ref_stack.back() = discarded;
|
*ref_stack.back() = discarded;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
assert(not ref_stack.empty());
|
assert(not ref_stack.empty());
|
||||||
assert(not keep_stack.empty());
|
assert(not keep_stack.empty());
|
||||||
ref_stack.pop_back();
|
ref_stack.pop_back();
|
||||||
keep_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
|
// 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())
|
||||||
|
@ -439,7 +444,6 @@ class json_sax_dom_callback_parser
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -453,13 +457,9 @@ class json_sax_dom_callback_parser
|
||||||
ref_stack.push_back(val.second);
|
ref_stack.push_back(val.second);
|
||||||
|
|
||||||
// check array limit
|
// 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;
|
return true;
|
||||||
|
@ -485,13 +485,10 @@ class json_sax_dom_callback_parser
|
||||||
keep_stack.pop_back();
|
keep_stack.pop_back();
|
||||||
|
|
||||||
// remove discarded value
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -506,16 +503,16 @@ class json_sax_dom_callback_parser
|
||||||
switch ((ex.id / 100) % 100)
|
switch ((ex.id / 100) % 100)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||||
case 4:
|
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
|
// LCOV_EXCL_START
|
||||||
case 2:
|
case 2:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||||
case 3:
|
case 3:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||||
case 5:
|
case 5:
|
||||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||||
default:
|
default:
|
||||||
assert(false);
|
assert(false);
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
@ -585,13 +582,15 @@ class json_sax_dom_callback_parser
|
||||||
// we now only expect arrays and objects
|
// we now only expect arrays and objects
|
||||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
||||||
|
|
||||||
|
// array
|
||||||
if (ref_stack.back()->is_array())
|
if (ref_stack.back()->is_array())
|
||||||
{
|
{
|
||||||
ref_stack.back()->m_value.array->push_back(std::move(value));
|
ref_stack.back()->m_value.array->push_back(std::move(value));
|
||||||
return {true, &(ref_stack.back()->m_value.array->back())};
|
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
|
// check if we should store an element for the current key
|
||||||
assert(not key_keep_stack.empty());
|
assert(not key_keep_stack.empty());
|
||||||
const bool store_element = key_keep_stack.back();
|
const bool store_element = key_keep_stack.back();
|
||||||
|
@ -606,16 +605,15 @@ class json_sax_dom_callback_parser
|
||||||
*object_element = std::move(value);
|
*object_element = std::move(value);
|
||||||
return {true, object_element};
|
return {true, object_element};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// stack to model hierarchy of values
|
||||||
std::vector<BasicJsonType*> ref_stack;
|
std::vector<BasicJsonType*> ref_stack {};
|
||||||
/// stack to manage which values to keep
|
/// 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
|
/// 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
|
/// helper to hold the reference for the next object element
|
||||||
BasicJsonType* object_element = nullptr;
|
BasicJsonType* object_element = nullptr;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
|
|
|
@ -1,16 +1,18 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <array> // array
|
||||||
#include <clocale> // localeconv
|
#include <clocale> // localeconv
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
|
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <string> // char_traits, string
|
#include <string> // char_traits, string
|
||||||
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/position_t.hpp>
|
#include <nlohmann/detail/input/position_t.hpp>
|
||||||
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
@ -148,22 +150,22 @@ class lexer
|
||||||
assert(current == 'u');
|
assert(current == 'u');
|
||||||
int codepoint = 0;
|
int codepoint = 0;
|
||||||
|
|
||||||
const auto factors = { 12, 8, 4, 0 };
|
const auto factors = { 12u, 8u, 4u, 0u };
|
||||||
for (const auto factor : factors)
|
for (const auto factor : factors)
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
|
|
||||||
if (current >= '0' and current <= '9')
|
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')
|
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')
|
else if (current >= 'a' and current <= 'f')
|
||||||
{
|
{
|
||||||
codepoint += ((current - 0x57) << factor);
|
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -321,15 +323,15 @@ class lexer
|
||||||
if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
|
if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
|
||||||
{
|
{
|
||||||
// overwrite codepoint
|
// overwrite codepoint
|
||||||
codepoint =
|
codepoint = static_cast<int>(
|
||||||
// high surrogate occupies the most significant 22 bits
|
// high surrogate occupies the most significant 22 bits
|
||||||
(codepoint1 << 10)
|
(static_cast<unsigned int>(codepoint1) << 10u)
|
||||||
// low surrogate occupies the least significant 15 bits
|
// low surrogate occupies the least significant 15 bits
|
||||||
+ codepoint2
|
+ static_cast<unsigned int>(codepoint2)
|
||||||
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
||||||
// in the result so we have to subtract with:
|
// in the result so we have to subtract with:
|
||||||
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
||||||
- 0x35FDC00;
|
- 0x35FDC00u);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -364,23 +366,23 @@ class lexer
|
||||||
else if (codepoint <= 0x7FF)
|
else if (codepoint <= 0x7FF)
|
||||||
{
|
{
|
||||||
// 2-byte characters: 110xxxxx 10xxxxxx
|
// 2-byte characters: 110xxxxx 10xxxxxx
|
||||||
add(0xC0 | (codepoint >> 6));
|
add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
|
||||||
add(0x80 | (codepoint & 0x3F));
|
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||||
}
|
}
|
||||||
else if (codepoint <= 0xFFFF)
|
else if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
add(0xE0 | (codepoint >> 12));
|
add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
|
||||||
add(0x80 | ((codepoint >> 6) & 0x3F));
|
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||||
add(0x80 | (codepoint & 0x3F));
|
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
add(0xF0 | (codepoint >> 18));
|
add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
|
||||||
add(0x80 | ((codepoint >> 12) & 0x3F));
|
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
|
||||||
add(0x80 | ((codepoint >> 6) & 0x3F));
|
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||||
add(0x80 | (codepoint & 0x3F));
|
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -906,13 +908,9 @@ class lexer
|
||||||
goto scan_number_any1;
|
goto scan_number_any1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// all other characters are rejected outside scan_number()
|
// all other characters are rejected outside scan_number()
|
||||||
assert(false);
|
default: // LCOV_EXCL_LINE
|
||||||
}
|
assert(false); // LCOV_EXCL_LINE
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_number_minus:
|
scan_number_minus:
|
||||||
|
@ -1297,7 +1295,7 @@ scan_number_done:
|
||||||
|
|
||||||
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
|
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
|
||||||
{
|
{
|
||||||
assert(token_string.size() != 0);
|
assert(not token_string.empty());
|
||||||
token_string.pop_back();
|
token_string.pop_back();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,9 +1357,9 @@ scan_number_done:
|
||||||
if ('\x00' <= c and c <= '\x1F')
|
if ('\x00' <= c and c <= '\x1F')
|
||||||
{
|
{
|
||||||
// escape control characters
|
// escape control characters
|
||||||
char cs[9];
|
std::array<char, 9> cs{};
|
||||||
(std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
|
(std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
|
||||||
result += cs;
|
result += cs.data();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1483,7 +1481,7 @@ scan_number_done:
|
||||||
bool next_unget = false;
|
bool next_unget = false;
|
||||||
|
|
||||||
/// the start position of the current token
|
/// the start position of the current token
|
||||||
position_t position;
|
position_t position {};
|
||||||
|
|
||||||
/// raw input token string (for error messages)
|
/// raw input token string (for error messages)
|
||||||
std::vector<char> token_string {};
|
std::vector<char> token_string {};
|
||||||
|
|
|
@ -6,13 +6,14 @@
|
||||||
#include <functional> // function
|
#include <functional> // function
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#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/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/json_sax.hpp>
|
#include <nlohmann/detail/input/json_sax.hpp>
|
||||||
#include <nlohmann/detail/input/lexer.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>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
|
@ -458,7 +459,7 @@ class parser
|
||||||
/// get next token from lexer
|
/// get next token from lexer
|
||||||
token_type get_token()
|
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)
|
std::string exception_message(const token_type expected, const std::string& context)
|
||||||
|
|
|
@ -23,5 +23,5 @@ struct position_t
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace nlohmann
|
||||||
|
|
|
@ -607,7 +607,7 @@ class iter_impl
|
||||||
/// associated JSON instance
|
/// associated JSON instance
|
||||||
pointer m_object = nullptr;
|
pointer m_object = nullptr;
|
||||||
/// the actual iterator of the associated instance
|
/// 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 detail
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
|
@ -1,12 +1,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <string> // string, to_string
|
|
||||||
#include <iterator> // input_iterator_tag
|
#include <iterator> // input_iterator_tag
|
||||||
|
#include <string> // string, to_string
|
||||||
#include <tuple> // tuple_size, get, tuple_element
|
#include <tuple> // tuple_size, get, tuple_element
|
||||||
|
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
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
|
// And see https://github.com/nlohmann/json/pull/1391
|
||||||
namespace std
|
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>
|
template <typename IteratorType>
|
||||||
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
|
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
|
||||||
: public std::integral_constant<std::size_t, 2> {};
|
: 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 <
|
get<N>(std::declval <
|
||||||
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
|
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
|
||||||
};
|
};
|
||||||
}
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#endif
|
||||||
|
} // namespace std
|
||||||
|
|
|
@ -45,5 +45,5 @@ struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
|
||||||
using pointer = T*;
|
using pointer = T*;
|
||||||
using reference = T&;
|
using reference = T&;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
}
|
} // namespace nlohmann
|
||||||
|
|
|
@ -4,10 +4,11 @@
|
||||||
#include <cassert> // assert
|
#include <cassert> // assert
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
|
@ -76,6 +77,139 @@ class json_pointer
|
||||||
return to_string();
|
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
|
@param[in] s reference token to be converted into an array index
|
||||||
|
|
||||||
|
@ -97,32 +231,9 @@ class json_pointer
|
||||||
return res;
|
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
|
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"));
|
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(),
|
std::all_of(reference_token.begin(), reference_token.end(),
|
||||||
[](const char x)
|
[](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
|
// 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,
|
friend bool operator==(json_pointer const& lhs,
|
||||||
json_pointer const& rhs) noexcept
|
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,
|
friend bool operator!=(json_pointer const& lhs,
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <utility> // pair
|
||||||
|
|
||||||
// This file contains all internal macro definitions
|
// This file contains all internal macro definitions
|
||||||
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
|
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
|
||||||
|
|
||||||
|
@ -37,6 +39,19 @@
|
||||||
#define JSON_DEPRECATED
|
#define JSON_DEPRECATED
|
||||||
#endif
|
#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
|
// allow to disable exceptions
|
||||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
||||||
#define JSON_THROW(exception) throw exception
|
#define JSON_THROW(exception) throw exception
|
||||||
|
@ -44,6 +59,7 @@
|
||||||
#define JSON_CATCH(exception) catch(exception)
|
#define JSON_CATCH(exception) catch(exception)
|
||||||
#define JSON_INTERNAL_CATCH(exception) catch(exception)
|
#define JSON_INTERNAL_CATCH(exception) catch(exception)
|
||||||
#else
|
#else
|
||||||
|
#include <cstdlib>
|
||||||
#define JSON_THROW(exception) std::abort()
|
#define JSON_THROW(exception) std::abort()
|
||||||
#define JSON_TRY if(true)
|
#define JSON_TRY if(true)
|
||||||
#define JSON_CATCH(exception) if(false)
|
#define JSON_CATCH(exception) if(false)
|
||||||
|
@ -72,8 +88,8 @@
|
||||||
|
|
||||||
// manual branch prediction
|
// manual branch prediction
|
||||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||||
#define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
#define JSON_LIKELY(x) __builtin_expect(static_cast<bool>(x), 1)
|
||||||
#define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
#define JSON_UNLIKELY(x) __builtin_expect(static_cast<bool>(x), 0)
|
||||||
#else
|
#else
|
||||||
#define JSON_LIKELY(x) x
|
#define JSON_LIKELY(x) x
|
||||||
#define JSON_UNLIKELY(x) x
|
#define JSON_UNLIKELY(x) x
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#undef JSON_LIKELY
|
#undef JSON_LIKELY
|
||||||
#undef JSON_UNLIKELY
|
#undef JSON_UNLIKELY
|
||||||
#undef JSON_DEPRECATED
|
#undef JSON_DEPRECATED
|
||||||
|
#undef JSON_NODISCARD
|
||||||
#undef JSON_HAS_CPP_14
|
#undef JSON_HAS_CPP_14
|
||||||
#undef JSON_HAS_CPP_17
|
#undef JSON_HAS_CPP_17
|
||||||
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||||
|
|
|
@ -14,7 +14,9 @@ struct nonesuch
|
||||||
nonesuch() = delete;
|
nonesuch() = delete;
|
||||||
~nonesuch() = delete;
|
~nonesuch() = delete;
|
||||||
nonesuch(nonesuch const&) = delete;
|
nonesuch(nonesuch const&) = delete;
|
||||||
|
nonesuch(nonesuch const&&) = delete;
|
||||||
void operator=(nonesuch const&) = delete;
|
void operator=(nonesuch const&) = delete;
|
||||||
|
void operator=(nonesuch&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class Default,
|
template <class Default,
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <cstdint> // size_t
|
#include <cstdint> // size_t
|
||||||
#include <utility> // declval
|
#include <utility> // declval
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
#include <nlohmann/detail/meta/detected.hpp>
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||||
#include <utility> // declval
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
|
||||||
#include <nlohmann/detail/iterators/iterator_traits.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/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/detected.hpp>
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
||||||
#include <cstring> // memcpy
|
#include <cstring> // memcpy
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
#include <nlohmann/detail/output/output_adapters.hpp>
|
||||||
|
@ -87,27 +88,27 @@ class binary_writer
|
||||||
// code from the value_t::number_unsigned case here.
|
// code from the value_t::number_unsigned case here.
|
||||||
if (j.m_value.number_integer <= 0x17)
|
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));
|
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));
|
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));
|
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
|
else
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(0x1B));
|
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
|
else
|
||||||
|
@ -117,27 +118,27 @@ class binary_writer
|
||||||
const auto positive_number = -1 - j.m_value.number_integer;
|
const auto positive_number = -1 - j.m_value.number_integer;
|
||||||
if (j.m_value.number_integer >= -24)
|
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));
|
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));
|
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));
|
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
|
else
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(0x3B));
|
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;
|
break;
|
||||||
|
@ -147,27 +148,27 @@ class binary_writer
|
||||||
{
|
{
|
||||||
if (j.m_value.number_unsigned <= 0x17)
|
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));
|
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));
|
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));
|
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
|
else
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(0x1B));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -185,28 +186,28 @@ class binary_writer
|
||||||
const auto N = j.m_value.string->size();
|
const auto N = j.m_value.string->size();
|
||||||
if (N <= 0x17)
|
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));
|
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));
|
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));
|
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
|
// 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));
|
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
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
|
@ -223,28 +224,28 @@ class binary_writer
|
||||||
const auto N = j.m_value.array->size();
|
const auto N = j.m_value.array->size();
|
||||||
if (N <= 0x17)
|
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));
|
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));
|
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));
|
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
|
// 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));
|
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
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
|
@ -262,28 +263,28 @@ class binary_writer
|
||||||
const auto N = j.m_value.object->size();
|
const auto N = j.m_value.object->size();
|
||||||
if (N <= 0x17)
|
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));
|
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));
|
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));
|
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
|
// 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));
|
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
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
|
@ -332,31 +333,31 @@ class binary_writer
|
||||||
if (j.m_value.number_unsigned < 128)
|
if (j.m_value.number_unsigned < 128)
|
||||||
{
|
{
|
||||||
// positive fixnum
|
// 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
|
// uint 8
|
||||||
oa->write_character(to_char_type(0xCC));
|
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
|
// uint 16
|
||||||
oa->write_character(to_char_type(0xCD));
|
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
|
// uint 32
|
||||||
oa->write_character(to_char_type(0xCE));
|
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
|
// uint 64
|
||||||
oa->write_character(to_char_type(0xCF));
|
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
|
else
|
||||||
|
@ -364,35 +365,35 @@ class binary_writer
|
||||||
if (j.m_value.number_integer >= -32)
|
if (j.m_value.number_integer >= -32)
|
||||||
{
|
{
|
||||||
// negative fixnum
|
// 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
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
|
||||||
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
// int 8
|
// int 8
|
||||||
oa->write_character(to_char_type(0xD0));
|
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
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
|
||||||
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||||
{
|
{
|
||||||
// int 16
|
// int 16
|
||||||
oa->write_character(to_char_type(0xD1));
|
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
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
|
||||||
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
// int 32
|
// int 32
|
||||||
oa->write_character(to_char_type(0xD2));
|
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
|
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
|
||||||
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
|
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
{
|
{
|
||||||
// int 64
|
// int 64
|
||||||
oa->write_character(to_char_type(0xD3));
|
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;
|
break;
|
||||||
|
@ -403,31 +404,31 @@ class binary_writer
|
||||||
if (j.m_value.number_unsigned < 128)
|
if (j.m_value.number_unsigned < 128)
|
||||||
{
|
{
|
||||||
// positive fixnum
|
// 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
|
// uint 8
|
||||||
oa->write_character(to_char_type(0xCC));
|
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
|
// uint 16
|
||||||
oa->write_character(to_char_type(0xCD));
|
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
|
// uint 32
|
||||||
oa->write_character(to_char_type(0xCE));
|
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
|
// uint 64
|
||||||
oa->write_character(to_char_type(0xCF));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -446,25 +447,25 @@ class binary_writer
|
||||||
if (N <= 31)
|
if (N <= 31)
|
||||||
{
|
{
|
||||||
// fixstr
|
// 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
|
// str 8
|
||||||
oa->write_character(to_char_type(0xD9));
|
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
|
// str 16
|
||||||
oa->write_character(to_char_type(0xDA));
|
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
|
// str 32
|
||||||
oa->write_character(to_char_type(0xDB));
|
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
|
// step 2: write the string
|
||||||
|
@ -481,19 +482,19 @@ class binary_writer
|
||||||
if (N <= 15)
|
if (N <= 15)
|
||||||
{
|
{
|
||||||
// fixarray
|
// 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
|
// array 16
|
||||||
oa->write_character(to_char_type(0xDC));
|
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
|
// array 32
|
||||||
oa->write_character(to_char_type(0xDD));
|
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
|
// step 2: write each element
|
||||||
|
@ -511,19 +512,19 @@ class binary_writer
|
||||||
if (N <= 15)
|
if (N <= 15)
|
||||||
{
|
{
|
||||||
// fixmap
|
// 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
|
// map 16
|
||||||
oa->write_character(to_char_type(0xDE));
|
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
|
// map 32
|
||||||
oa->write_character(to_char_type(0xDF));
|
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
|
// 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)
|
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 (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
|
||||||
{
|
? sizeof(std::int32_t)
|
||||||
return sizeof(std::int32_t);
|
: sizeof(std::int64_t);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return sizeof(std::int64_t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -1064,45 +1060,45 @@ class binary_writer
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
void write_number_with_ubjson_prefix(const NumberType n,
|
||||||
const bool add_prefix)
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('i')); // int8
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('U')); // uint8
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('I')); // int16
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('l')); // int32
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('L')); // int64
|
oa->write_character(to_char_type('L')); // int64
|
||||||
}
|
}
|
||||||
write_number(static_cast<int64_t>(n));
|
write_number(static_cast<std::int64_t>(n));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1117,45 +1113,45 @@ class binary_writer
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
void write_number_with_ubjson_prefix(const NumberType n,
|
||||||
const bool add_prefix)
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('i')); // int8
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('U')); // uint8
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('I')); // int16
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('l')); // int32
|
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)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type('L')); // int64
|
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
|
// LCOV_EXCL_START
|
||||||
else
|
else
|
||||||
|
@ -1186,19 +1182,19 @@ class binary_writer
|
||||||
|
|
||||||
case value_t::number_integer:
|
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';
|
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';
|
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';
|
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';
|
return 'l';
|
||||||
}
|
}
|
||||||
|
@ -1208,19 +1204,19 @@ class binary_writer
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
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';
|
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';
|
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';
|
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';
|
return 'l';
|
||||||
}
|
}
|
||||||
|
@ -1278,7 +1274,7 @@ class binary_writer
|
||||||
std::memcpy(vec.data(), &n, sizeof(NumberType));
|
std::memcpy(vec.data(), &n, sizeof(NumberType));
|
||||||
|
|
||||||
// step 2: write array to output (with possible reordering)
|
// 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
|
// reverse byte order prior to conversion if necessary
|
||||||
std::reverse(vec.begin(), vec.end());
|
std::reverse(vec.begin(), vec.end());
|
||||||
|
|
|
@ -12,9 +12,10 @@
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <type_traits> // is_same
|
#include <type_traits> // is_same
|
||||||
|
#include <utility> // move
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
|
||||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||||
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/output/binary_writer.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_float_t = typename BasicJsonType::number_float_t;
|
||||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
static constexpr uint8_t UTF8_ACCEPT = 0;
|
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||||
static constexpr uint8_t UTF8_REJECT = 1;
|
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@ -277,6 +278,9 @@ class serializer
|
||||||
o->write_characters("null", 4);
|
o->write_characters("null", 4);
|
||||||
return;
|
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)
|
void dump_escaped(const string_t& s, const bool ensure_ascii)
|
||||||
{
|
{
|
||||||
uint32_t codepoint;
|
std::uint32_t codepoint;
|
||||||
uint8_t state = UTF8_ACCEPT;
|
std::uint8_t state = UTF8_ACCEPT;
|
||||||
std::size_t bytes = 0; // number of bytes written to string_buffer
|
std::size_t bytes = 0; // number of bytes written to string_buffer
|
||||||
|
|
||||||
// number of bytes written at the point of the last valid byte
|
// number of bytes written at the point of the last valid byte
|
||||||
|
@ -373,14 +377,14 @@ class serializer
|
||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
||||||
static_cast<uint16_t>(codepoint));
|
static_cast<std::uint16_t>(codepoint));
|
||||||
bytes += 6;
|
bytes += 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
||||||
static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
|
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
||||||
static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
|
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
|
||||||
bytes += 12;
|
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('\xBF');
|
||||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
|
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;
|
bytes_after_last_accept = bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,6 +477,9 @@ class serializer
|
||||||
state = UTF8_ACCEPT;
|
state = UTF8_ACCEPT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default: // LCOV_EXCL_LINE
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -497,7 +514,7 @@ class serializer
|
||||||
case error_handler_t::strict:
|
case error_handler_t::strict:
|
||||||
{
|
{
|
||||||
std::string sn(3, '\0');
|
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));
|
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -523,6 +540,9 @@ class serializer
|
||||||
}
|
}
|
||||||
break;
|
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
|
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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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'},
|
{{'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
|
// 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
|
const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
@ -610,7 +630,7 @@ class serializer
|
||||||
if (is_negative)
|
if (is_negative)
|
||||||
{
|
{
|
||||||
*buffer_ptr = '-';
|
*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
|
// account one more byte for the minus sign
|
||||||
n_chars = 1 + count_digits(abs_value);
|
n_chars = 1 + count_digits(abs_value);
|
||||||
|
@ -630,7 +650,6 @@ class serializer
|
||||||
|
|
||||||
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
|
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
|
||||||
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
|
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
|
||||||
const auto buffer_end = buffer_ptr;
|
|
||||||
while (abs_value >= 100)
|
while (abs_value >= 100)
|
||||||
{
|
{
|
||||||
const auto digits_index = static_cast<unsigned>((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,
|
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
||||||
[](char c)
|
[](char c)
|
||||||
{
|
{
|
||||||
return (c == '.' or c == 'e');
|
return c == '.' or c == 'e';
|
||||||
});
|
});
|
||||||
|
|
||||||
if (value_is_int_like)
|
if (value_is_int_like)
|
||||||
|
@ -760,9 +779,9 @@ class serializer
|
||||||
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||||
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
@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
|
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)
|
codep = (state != UTF8_ACCEPT)
|
||||||
? (byte & 0x3fu) | (codep << 6)
|
? (byte & 0x3fu) | (codep << 6u)
|
||||||
: static_cast<uint32_t>(0xff >> type) & (byte);
|
: (0xFFu >> type) & (byte);
|
||||||
|
|
||||||
state = utf8d[256u + state * 16u + type];
|
state = utf8d[256u + state * 16u + type];
|
||||||
return state;
|
return state;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <ciso646> // and
|
#include <ciso646> // and
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
namespace nlohmann
|
namespace nlohmann
|
||||||
{
|
{
|
||||||
|
|
|
@ -27,8 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_HPP
|
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
|
||||||
#define NLOHMANN_JSON_HPP
|
#define INCLUDE_NLOHMANN_JSON_HPP_
|
||||||
|
|
||||||
#define NLOHMANN_JSON_VERSION_MAJOR 3
|
#define NLOHMANN_JSON_VERSION_MAJOR 3
|
||||||
#define NLOHMANN_JSON_VERSION_MINOR 5
|
#define NLOHMANN_JSON_VERSION_MINOR 5
|
||||||
|
@ -42,33 +42,35 @@ SOFTWARE.
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iosfwd> // istream, ostream
|
#include <iosfwd> // istream, ostream
|
||||||
#include <iterator> // random_access_iterator_tag
|
#include <iterator> // random_access_iterator_tag
|
||||||
|
#include <memory> // unique_ptr
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string, stoi, to_string
|
#include <string> // string, stoi, to_string
|
||||||
#include <utility> // declval, forward, move, pair, swap
|
#include <utility> // declval, forward, move, pair, swap
|
||||||
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/adl_serializer.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/detail/conversions/from_json.hpp>
|
#include <nlohmann/detail/conversions/from_json.hpp>
|
||||||
#include <nlohmann/detail/conversions/to_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/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/lexer.hpp>
|
#include <nlohmann/detail/input/lexer.hpp>
|
||||||
#include <nlohmann/detail/input/parser.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/internal_iterator.hpp>
|
||||||
#include <nlohmann/detail/iterators/iter_impl.hpp>
|
#include <nlohmann/detail/iterators/iter_impl.hpp>
|
||||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||||
#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
|
#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
|
||||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
#include <nlohmann/detail/iterators/primitive_iterator.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/json_pointer.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
|
@brief namespace for Niels Lohmann
|
||||||
|
@ -317,6 +319,7 @@ class basic_json
|
||||||
|
|
||||||
@since 2.1.0
|
@since 2.1.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json meta()
|
static basic_json meta()
|
||||||
{
|
{
|
||||||
basic_json result;
|
basic_json result;
|
||||||
|
@ -1322,6 +1325,8 @@ class basic_json
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
m_type = value_t::discarded;
|
m_type = value_t::discarded;
|
||||||
break;
|
break;
|
||||||
|
default: // LCOV_EXCL_LINE
|
||||||
|
assert(false); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
}
|
}
|
||||||
|
@ -1409,7 +1414,7 @@ class basic_json
|
||||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||||
[](const detail::json_ref<basic_json>& element_ref)
|
[](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
|
// adjust type if type deduction is not wanted
|
||||||
|
@ -1489,6 +1494,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json array(initializer_list_t init = {})
|
static basic_json array(initializer_list_t init = {})
|
||||||
{
|
{
|
||||||
return basic_json(init, false, value_t::array);
|
return basic_json(init, false, value_t::array);
|
||||||
|
@ -1532,6 +1538,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json object(initializer_list_t init = {})
|
static basic_json object(initializer_list_t init = {})
|
||||||
{
|
{
|
||||||
return basic_json(init, false, value_t::object);
|
return basic_json(init, false, value_t::object);
|
||||||
|
@ -2092,7 +2099,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
constexpr bool is_null() const noexcept
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
#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
|
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
|
and not std::is_same<ValueType, typename std::string_view>::value
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
@ -3894,6 +3901,8 @@ class basic_json
|
||||||
|
|
||||||
@liveexample{The example shows how `find()` is used.,find__key_type}
|
@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
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
template<typename KeyT>
|
template<typename KeyT>
|
||||||
|
@ -3954,6 +3963,36 @@ class basic_json
|
||||||
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
|
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)
|
switch (lhs_type)
|
||||||
{
|
{
|
||||||
case value_t::array:
|
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:
|
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:
|
case value_t::null:
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
case value_t::string:
|
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:
|
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:
|
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:
|
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:
|
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:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -5559,27 +5598,27 @@ class basic_json
|
||||||
}
|
}
|
||||||
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
|
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)
|
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)
|
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)
|
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)
|
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)
|
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;
|
return false;
|
||||||
|
@ -5593,7 +5632,7 @@ class basic_json
|
||||||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
|
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)
|
switch (lhs_type)
|
||||||
{
|
{
|
||||||
case value_t::array:
|
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:
|
case value_t::object:
|
||||||
return *lhs.m_value.object < *rhs.m_value.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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
|
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>
|
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||||
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
|
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)
|
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
|
||||||
{
|
{
|
||||||
// read width member and use it as indentation parameter if nonzero
|
// read width member and use it as indentation parameter if nonzero
|
||||||
const bool pretty_print = (o.width() > 0);
|
const bool pretty_print = o.width() > 0;
|
||||||
const auto indentation = (pretty_print ? o.width() : 0);
|
const auto indentation = pretty_print ? o.width() : 0;
|
||||||
|
|
||||||
// reset width to 0 for subsequent calls to this stream
|
// reset width to 0 for subsequent calls to this stream
|
||||||
o.width(0);
|
o.width(0);
|
||||||
|
@ -6006,9 +6045,6 @@ class basic_json
|
||||||
@pre The container storage is contiguous. Violating this precondition
|
@pre The container storage is contiguous. Violating this precondition
|
||||||
yields undefined behavior. **This precondition is enforced with an
|
yields undefined behavior. **This precondition is enforced with an
|
||||||
assertion.**
|
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
|
@warning There is no way to enforce all preconditions at compile-time. If
|
||||||
the function is called with a noncompliant container and with
|
the function is called with a noncompliant container and with
|
||||||
|
@ -6051,6 +6087,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 2.0.3 (contiguous containers)
|
@since version 2.0.3 (contiguous containers)
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json parse(detail::input_adapter&& i,
|
static basic_json parse(detail::input_adapter&& i,
|
||||||
const parser_callback_t cb = nullptr,
|
const parser_callback_t cb = nullptr,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -6088,9 +6125,6 @@ class basic_json
|
||||||
@pre The container storage is contiguous. Violating this precondition
|
@pre The container storage is contiguous. Violating this precondition
|
||||||
yields undefined behavior. **This precondition is enforced with an
|
yields undefined behavior. **This precondition is enforced with an
|
||||||
assertion.**
|
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
|
@warning There is no way to enforce all preconditions at compile-time. If
|
||||||
the function is called with a noncompliant container and with
|
the function is called with a noncompliant container and with
|
||||||
|
@ -6127,13 +6161,9 @@ class basic_json
|
||||||
const bool strict = true)
|
const bool strict = true)
|
||||||
{
|
{
|
||||||
assert(sax);
|
assert(sax);
|
||||||
switch (format)
|
return format == input_format_t::json
|
||||||
{
|
? parser(std::move(i)).sax_parse(sax, strict)
|
||||||
case input_format_t::json:
|
: detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -6826,6 +6856,7 @@ class basic_json
|
||||||
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
|
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json from_cbor(detail::input_adapter&& i,
|
static basic_json from_cbor(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -6841,6 +6872,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename A1, typename A2,
|
template<typename A1, typename A2,
|
||||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
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,
|
static basic_json from_cbor(A1 && a1, A2 && a2,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = 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
|
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
|
||||||
since 3.2.0
|
since 3.2.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json from_msgpack(detail::input_adapter&& i,
|
static basic_json from_msgpack(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -6948,6 +6981,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename A1, typename A2,
|
template<typename A1, typename A2,
|
||||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
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,
|
static basic_json from_msgpack(A1 && a1, A2 && a2,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = 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
|
@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,
|
static basic_json from_ubjson(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -7034,6 +7069,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename A1, typename A2,
|
template<typename A1, typename A2,
|
||||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
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,
|
static basic_json from_ubjson(A1 && a1, A2 && a2,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = 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
|
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
|
||||||
related UBJSON format
|
related UBJSON format
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json from_bson(detail::input_adapter&& i,
|
static basic_json from_bson(detail::input_adapter&& i,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -7119,6 +7156,7 @@ class basic_json
|
||||||
*/
|
*/
|
||||||
template<typename A1, typename A2,
|
template<typename A1, typename A2,
|
||||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
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,
|
static basic_json from_bson(A1 && a1, A2 && a2,
|
||||||
const bool strict = true,
|
const bool strict = true,
|
||||||
const bool allow_exceptions = true)
|
const bool allow_exceptions = true)
|
||||||
|
@ -7454,12 +7492,12 @@ class basic_json
|
||||||
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
|
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
|
||||||
{
|
{
|
||||||
// adding to the root of the target document means replacing it
|
// adding to the root of the target document means replacing it
|
||||||
if (ptr.is_root())
|
if (ptr.empty())
|
||||||
{
|
{
|
||||||
result = val;
|
result = val;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// make sure the top element of the pointer exists
|
// make sure the top element of the pointer exists
|
||||||
json_pointer top_pointer = ptr.top();
|
json_pointer top_pointer = ptr.top();
|
||||||
if (top_pointer != ptr)
|
if (top_pointer != ptr)
|
||||||
|
@ -7503,14 +7541,9 @@ class basic_json
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// LCOV_EXCL_START
|
|
||||||
default:
|
|
||||||
{
|
|
||||||
// if there exists a parent it cannot be primitive
|
// if there exists a parent it cannot be primitive
|
||||||
assert(false);
|
default: // LCOV_EXCL_LINE
|
||||||
}
|
assert(false); // LCOV_EXCL_LINE
|
||||||
// LCOV_EXCL_STOP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7665,7 +7698,7 @@ class basic_json
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case patch_operations::invalid:
|
default:
|
||||||
{
|
{
|
||||||
// op must be "add", "remove", "replace", "move", "copy", or
|
// op must be "add", "remove", "replace", "move", "copy", or
|
||||||
// "test"
|
// "test"
|
||||||
|
@ -7710,6 +7743,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 2.0.0
|
@since version 2.0.0
|
||||||
*/
|
*/
|
||||||
|
JSON_NODISCARD
|
||||||
static basic_json diff(const basic_json& source, const basic_json& target,
|
static basic_json diff(const basic_json& source, const basic_json& target,
|
||||||
const std::string& path = "")
|
const std::string& path = "")
|
||||||
{
|
{
|
||||||
|
@ -7729,9 +7763,9 @@ class basic_json
|
||||||
{
|
{
|
||||||
{"op", "replace"}, {"path", path}, {"value", target}
|
{"op", "replace"}, {"path", path}, {"value", target}
|
||||||
});
|
});
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (source.type())
|
switch (source.type())
|
||||||
{
|
{
|
||||||
case value_t::array:
|
case value_t::array:
|
||||||
|
@ -7830,7 +7864,6 @@ class basic_json
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -8012,4 +8045,4 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_unscope.hpp>
|
#include <nlohmann/detail/macro_unscope.hpp>
|
||||||
|
|
||||||
#endif
|
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#ifndef NLOHMANN_JSON_FWD_HPP
|
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
#define NLOHMANN_JSON_FWD_HPP
|
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
|
@ -61,4 +61,4 @@ uses the standard template types.
|
||||||
using json = basic_json<>;
|
using json = basic_json<>;
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
|
|
||||||
#endif
|
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
|
|
|
@ -12,6 +12,7 @@ nlohmann_json_multiple_headers = declare_dependency(
|
||||||
include_directories: include_directories('include')
|
include_directories: include_directories('include')
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if not meson.is_subproject()
|
||||||
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
||||||
|
|
||||||
pkgc = import('pkgconfig')
|
pkgc = import('pkgconfig')
|
||||||
|
@ -19,3 +20,4 @@ pkgc.generate(name: 'nlohmann_json',
|
||||||
version: meson.project_version(),
|
version: meson.project_version(),
|
||||||
description: 'JSON for Modern C++'
|
description: 'JSON for Modern C++'
|
||||||
)
|
)
|
||||||
|
endif
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -64,7 +64,12 @@ set_target_properties(doctest_main PROPERTIES
|
||||||
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
|
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
|
||||||
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
|
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")
|
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
|
||||||
|
|
||||||
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
|
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
|
||||||
|
|
|
@ -111,6 +111,12 @@ struct my_allocator : std::allocator<T>
|
||||||
p->~T();
|
p->~T();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <class U>
|
||||||
|
struct rebind
|
||||||
|
{
|
||||||
|
using other = my_allocator<U>;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// allows deletion of raw pointer, usually hold by json_value
|
// allows deletion of raw pointer, usually hold by json_value
|
||||||
|
|
|
@ -150,7 +150,7 @@ class alt_string
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string str_impl;
|
std::string str_impl {};
|
||||||
|
|
||||||
friend bool ::operator<(const char*, const alt_string&);
|
friend bool ::operator<(const char*, const alt_string&);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1968,7 +1968,7 @@ TEST_CASE("all CBOR first bytes")
|
||||||
|
|
||||||
try
|
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)
|
catch (const json::parse_error& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -126,7 +126,7 @@ class SaxEventLogger
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> events;
|
std::vector<std::string> events {};
|
||||||
bool errored = false;
|
bool errored = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> events;
|
std::vector<std::string> events {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -439,6 +439,7 @@ TEST_CASE("JSON pointers")
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
CHECK(json::json_pointer(ptr).to_string() == ptr);
|
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());
|
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");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -308,7 +308,7 @@ TEST_CASE("README" * doctest::skip())
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// calculate a JSON patch from two JSON values
|
// 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":" replace", "path": "/baz", "value": ["one", "two", "three"] },
|
||||||
// { "op":"remove","path":"/hello" },
|
// { "op":"remove","path":"/hello" },
|
||||||
|
|
|
@ -129,8 +129,10 @@ struct nocopy
|
||||||
|
|
||||||
struct Data
|
struct Data
|
||||||
{
|
{
|
||||||
std::string a;
|
Data() = default;
|
||||||
std::string b;
|
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)
|
void from_json(const json& j, Data& data)
|
||||||
|
@ -1712,6 +1714,74 @@ TEST_CASE("regression tests")
|
||||||
const auto data = j.get<decltype(expected)>();
|
const auto data = j.get<decltype(expected)>();
|
||||||
CHECK(expected == data);
|
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)
|
#if not defined(JSON_NOEXCEPTION)
|
||||||
|
|
|
@ -2130,7 +2130,7 @@ TEST_CASE("all UBJSON first bytes")
|
||||||
|
|
||||||
try
|
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)
|
catch (const json::parse_error& e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -598,9 +598,8 @@ struct pod_serializer
|
||||||
static void to_json(BasicJsonType& j, const T& t) noexcept
|
static void to_json(BasicJsonType& j, const T& t) noexcept
|
||||||
{
|
{
|
||||||
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
|
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
|
||||||
std::uint64_t value = bytes[0];
|
std::uint64_t value;
|
||||||
for (auto i = 1; i < 8; ++i)
|
std::memcpy(&value, bytes, sizeof(value));
|
||||||
value |= std::uint64_t{bytes[i]} << 8 * i;
|
|
||||||
nlohmann::to_json(j, value);
|
nlohmann::to_json(j, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
27
third_party/cpplint/LICENSE
vendored
Executable file
27
third_party/cpplint/LICENSE
vendored
Executable 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
Executable file
80
third_party/cpplint/README.rst
vendored
Executable 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
Executable file
6583
third_party/cpplint/cpplint.py
vendored
Executable file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue