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
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode6.4
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode7.3
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.1
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.2
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode8.3
|
||||
|
||||
|
@ -164,6 +149,9 @@ matrix:
|
|||
- os: osx
|
||||
osx_image: xcode10
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode10.1
|
||||
|
||||
# Linux / GCC
|
||||
|
||||
- os: linux
|
||||
|
@ -290,15 +278,23 @@ matrix:
|
|||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
|
||||
packages: ['g++-6', 'clang-6.0', 'ninja-build']
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env: COMPILER=clang++-7
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
|
||||
packages: ['g++-6', 'clang-7', 'ninja-build']
|
||||
|
||||
- os: linux
|
||||
compiler: clang
|
||||
env:
|
||||
- COMPILER=clang++-6.0
|
||||
- COMPILER=clang++-7
|
||||
- CXXFLAGS=-std=c++1z
|
||||
addons:
|
||||
apt:
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-6.0']
|
||||
packages: ['g++-6', 'clang-6.0', 'ninja-build']
|
||||
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-trusty-7']
|
||||
packages: ['g++-6', 'clang-7', 'ninja-build']
|
||||
|
||||
################
|
||||
# build script #
|
||||
|
|
|
@ -16,6 +16,7 @@ include(ExternalProject)
|
|||
## OPTIONS
|
||||
##
|
||||
option(JSON_BuildTests "Build the unit tests when BUILD_TESTING is enabled." ON)
|
||||
option(JSON_Install "Install CMake targets during install step." ON)
|
||||
option(JSON_MultipleHeaders "Use non-amalgamated version of the library." OFF)
|
||||
|
||||
##
|
||||
|
@ -46,7 +47,11 @@ endif()
|
|||
##
|
||||
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
|
||||
add_library(${PROJECT_NAME}::${NLOHMANN_JSON_TARGET_NAME} ALIAS ${NLOHMANN_JSON_TARGET_NAME})
|
||||
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
|
||||
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_range_for)
|
||||
else()
|
||||
target_compile_features(${NLOHMANN_JSON_TARGET_NAME} INTERFACE cxx_std_11)
|
||||
endif()
|
||||
|
||||
target_include_directories(
|
||||
${NLOHMANN_JSON_TARGET_NAME}
|
||||
|
@ -92,32 +97,34 @@ configure_file(
|
|||
@ONLY
|
||||
)
|
||||
|
||||
install(
|
||||
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
|
||||
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
install(
|
||||
FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
|
||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
if (NLOHMANN_ADD_NATVIS)
|
||||
if(JSON_Install)
|
||||
install(
|
||||
FILES ${NLOHMANN_NATVIS_FILE}
|
||||
DESTINATION .
|
||||
)
|
||||
DIRECTORY ${NLOHMANN_JSON_INCLUDE_BUILD_DIR}
|
||||
DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
install(
|
||||
FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
|
||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
if (NLOHMANN_ADD_NATVIS)
|
||||
install(
|
||||
FILES ${NLOHMANN_NATVIS_FILE}
|
||||
DESTINATION .
|
||||
)
|
||||
endif()
|
||||
export(
|
||||
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
|
||||
)
|
||||
install(
|
||||
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
|
||||
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||
INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
install(
|
||||
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
endif()
|
||||
export(
|
||||
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
FILE ${NLOHMANN_JSON_CMAKE_PROJECT_TARGETS_FILE}
|
||||
)
|
||||
install(
|
||||
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
|
||||
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||
INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
install(
|
||||
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||
NAMESPACE ${PROJECT_NAME}::
|
||||
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||
)
|
||||
|
|
214
Makefile
214
Makefile
|
@ -49,6 +49,9 @@ all:
|
|||
@echo "clean - remove built files"
|
||||
@echo "coverage - create coverage information with lcov"
|
||||
@echo "cppcheck - analyze code with cppcheck"
|
||||
@echo "cpplint - analyze code with cpplint"
|
||||
@echo "clang_tidy - analyze code with Clang-Tidy"
|
||||
@echo "clang_analyze - analyze code with Clang-Analyzer"
|
||||
@echo "doctest - compile example files and check their output"
|
||||
@echo "fuzz_testing - prepare fuzz testing of the JSON parser"
|
||||
@echo "fuzz_testing_bson - prepare fuzz testing of the BSON parser"
|
||||
|
@ -122,7 +125,7 @@ doctest:
|
|||
# -Wno-c++2a-compat: u8 literals will behave differently in C++20...
|
||||
# -Wno-padded: padding is nothing to warn about
|
||||
pedantic_clang:
|
||||
$(MAKE) json_unit CXX=$(COMPILER_DIR)/clang++ CXXFLAGS="\
|
||||
$(MAKE) json_unit CXX=$(COMPILER_DIR)/clang++ CXXFLAGS=" \
|
||||
-std=c++11 -Wno-c++98-compat -Wno-c++98-compat-pedantic \
|
||||
-Werror \
|
||||
-Weverything \
|
||||
|
@ -134,72 +137,233 @@ pedantic_clang:
|
|||
-Wno-float-equal \
|
||||
-Wno-switch-enum -Wno-covered-switch-default \
|
||||
-Wno-c++2a-compat \
|
||||
-Wno-c++17-extensions \
|
||||
-Wno-padded"
|
||||
|
||||
# calling GCC with most warnings
|
||||
pedantic_gcc:
|
||||
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS="\
|
||||
$(MAKE) json_unit CXX=$(COMPILER_DIR)/g++ CXXFLAGS=" \
|
||||
-std=c++11 \
|
||||
-Wno-deprecated-declarations \
|
||||
-Werror \
|
||||
-Wall -Wpedantic -Wextra \
|
||||
-Waddress \
|
||||
-Waddress-of-packed-member \
|
||||
-Waggressive-loop-optimizations \
|
||||
-Waligned-new=all \
|
||||
-Wall \
|
||||
-Walloc-zero \
|
||||
-Walloca \
|
||||
-Warray-bounds \
|
||||
-Warray-bounds=2 \
|
||||
-Wcast-qual -Wcast-align \
|
||||
-Wattribute-alias=2 \
|
||||
-Wattribute-warning \
|
||||
-Wattributes \
|
||||
-Wbool-compare \
|
||||
-Wbool-operation \
|
||||
-Wbuiltin-declaration-mismatch \
|
||||
-Wbuiltin-macro-redefined \
|
||||
-Wcannot-profile \
|
||||
-Wcast-align \
|
||||
-Wcast-function-type \
|
||||
-Wcast-qual \
|
||||
-Wcatch-value=3 \
|
||||
-Wchar-subscripts \
|
||||
-Wclass-conversion \
|
||||
-Wclass-memaccess \
|
||||
-Wclobbered \
|
||||
-Wcomment \
|
||||
-Wcomments \
|
||||
-Wconditionally-supported \
|
||||
-Wconversion \
|
||||
-Wconversion-null \
|
||||
-Wcoverage-mismatch \
|
||||
-Wcpp \
|
||||
-Wctor-dtor-privacy \
|
||||
-Wdangling-else \
|
||||
-Wdate-time \
|
||||
-Wdelete-incomplete \
|
||||
-Wdelete-non-virtual-dtor \
|
||||
-Wdeprecated \
|
||||
-Wdeprecated-copy \
|
||||
-Wdeprecated-copy-dtor \
|
||||
-Wdeprecated-declarations \
|
||||
-Wdisabled-optimization \
|
||||
-Wdiv-by-zero \
|
||||
-Wdouble-promotion \
|
||||
-Wduplicated-branches \
|
||||
-Wduplicated-cond \
|
||||
-Weffc++ \
|
||||
-Wempty-body \
|
||||
-Wendif-labels \
|
||||
-Wenum-compare \
|
||||
-Wexpansion-to-defined \
|
||||
-Werror \
|
||||
-Wextra \
|
||||
-Wextra-semi \
|
||||
-Wfloat-conversion \
|
||||
-Wfloat-equal \
|
||||
-Wformat \
|
||||
-Wformat-contains-nul \
|
||||
-Wformat-extra-args \
|
||||
-Wformat-nonliteral \
|
||||
-Wformat-overflow=2 \
|
||||
-Wformat-security \
|
||||
-Wformat-signedness \
|
||||
-Wformat-truncation=2 \
|
||||
-Wformat-y2k \
|
||||
-Wformat-zero-length \
|
||||
-Wformat=2 \
|
||||
-Wno-ignored-qualifiers \
|
||||
-Wframe-address \
|
||||
-Wfree-nonheap-object \
|
||||
-Whsa \
|
||||
-Wif-not-aligned \
|
||||
-Wignored-attributes \
|
||||
-Wignored-qualifiers \
|
||||
-Wimplicit-fallthrough=5 \
|
||||
-Winherited-variadic-ctor \
|
||||
-Winit-list-lifetime \
|
||||
-Winit-self \
|
||||
-Winline \
|
||||
-Wint-in-bool-context \
|
||||
-Wint-to-pointer-cast \
|
||||
-Winvalid-memory-model \
|
||||
-Winvalid-offsetof \
|
||||
-Winvalid-pch \
|
||||
-Wliteral-suffix \
|
||||
-Wlogical-not-parentheses \
|
||||
-Wlogical-op \
|
||||
-Wlto-type-mismatch \
|
||||
-Wmain \
|
||||
-Wmaybe-uninitialized \
|
||||
-Wmemset-elt-size \
|
||||
-Wmemset-transposed-args \
|
||||
-Wmisleading-indentation \
|
||||
-Wmissing-attributes \
|
||||
-Wmissing-braces \
|
||||
-Wmissing-declarations \
|
||||
-Wmissing-field-initializers \
|
||||
-Wmissing-format-attribute \
|
||||
-Wmissing-include-dirs \
|
||||
-Wmissing-noreturn \
|
||||
-Wmissing-profile \
|
||||
-Wmultichar \
|
||||
-Wmultiple-inheritance \
|
||||
-Wmultistatement-macros \
|
||||
-Wnarrowing \
|
||||
-Wno-deprecated-declarations \
|
||||
-Wno-long-long \
|
||||
-Wno-namespaces \
|
||||
-Wno-padded \
|
||||
-Wno-switch-enum \
|
||||
-Wno-system-headers \
|
||||
-Wno-templates \
|
||||
-Wno-undef \
|
||||
-Wnoexcept \
|
||||
-Wnoexcept-type \
|
||||
-Wnon-template-friend \
|
||||
-Wnon-virtual-dtor \
|
||||
-Wnonnull \
|
||||
-Wnonnull-compare \
|
||||
-Wnonportable-cfstrings \
|
||||
-Wnormalized \
|
||||
-Wnull-dereference \
|
||||
-Wodr \
|
||||
-Wold-style-cast \
|
||||
-Wopenmp-simd \
|
||||
-Woverflow \
|
||||
-Woverlength-strings \
|
||||
-Woverloaded-virtual \
|
||||
-Wpacked \
|
||||
-Wpacked-bitfield-compat \
|
||||
-Wpacked-not-aligned \
|
||||
-Wparentheses \
|
||||
-Wpedantic \
|
||||
-Wpessimizing-move \
|
||||
-Wplacement-new=2 \
|
||||
-Wpmf-conversions \
|
||||
-Wpointer-arith \
|
||||
-Wpointer-compare \
|
||||
-Wpragmas \
|
||||
-Wprio-ctor-dtor \
|
||||
-Wpsabi \
|
||||
-Wredundant-decls \
|
||||
-Wredundant-move \
|
||||
-Wregister \
|
||||
-Wreorder \
|
||||
-Wrestrict \
|
||||
-Wreturn-local-addr \
|
||||
-Wreturn-type \
|
||||
-Wscalar-storage-order \
|
||||
-Wsequence-point \
|
||||
-Wshadow \
|
||||
-Wshadow-compatible-local \
|
||||
-Wshadow-local \
|
||||
-Wshadow=compatible-local \
|
||||
-Wshadow=global \
|
||||
-Wshadow=local \
|
||||
-Wshift-count-negative \
|
||||
-Wshift-count-overflow \
|
||||
-Wshift-negative-value \
|
||||
-Wshift-overflow=2 \
|
||||
-Wsign-compare \
|
||||
-Wsign-conversion \
|
||||
-Wsign-promo \
|
||||
-Wsized-deallocation \
|
||||
-Wsizeof-array-argument \
|
||||
-Wsizeof-pointer-div \
|
||||
-Wsizeof-pointer-memaccess \
|
||||
-Wstack-protector \
|
||||
-Wstrict-aliasing=3 \
|
||||
-Wstrict-null-sentinel \
|
||||
-Wstrict-overflow=5 \
|
||||
-Wstringop-overflow=4 \
|
||||
-Wstringop-truncation \
|
||||
-Wsubobject-linkage \
|
||||
-Wsuggest-attribute=cold \
|
||||
-Wsuggest-attribute=const \
|
||||
-Wsuggest-attribute=format \
|
||||
-Wsuggest-attribute=malloc \
|
||||
-Wsuggest-attribute=noreturn \
|
||||
-Wsuggest-attribute=pure \
|
||||
-Wsuggest-final-methods \
|
||||
-Wsuggest-final-types \
|
||||
-Wsuggest-override \
|
||||
-Wswitch \
|
||||
-Wswitch-bool \
|
||||
-Wswitch-default \
|
||||
-Wswitch-unreachable \
|
||||
-Wsync-nand \
|
||||
-Wsynth \
|
||||
-Wtautological-compare \
|
||||
-Wterminate \
|
||||
-Wtrampolines \
|
||||
-Wtrigraphs \
|
||||
-Wundef \
|
||||
-Wuninitialized -Wunknown-pragmas \
|
||||
-Wtype-limits \
|
||||
-Wuninitialized \
|
||||
-Wunknown-pragmas \
|
||||
-Wunreachable-code \
|
||||
-Wunsafe-loop-optimizations \
|
||||
-Wunused \
|
||||
-Wunused-but-set-parameter \
|
||||
-Wunused-but-set-variable \
|
||||
-Wunused-const-variable=2 \
|
||||
-Wunused-function \
|
||||
-Wunused-label \
|
||||
-Wunused-local-typedefs \
|
||||
-Wunused-macros \
|
||||
-Wunused-parameter \
|
||||
-Wunused-result \
|
||||
-Wunused-value \
|
||||
-Wunused-variable \
|
||||
-Wuseless-cast \
|
||||
-Wvarargs \
|
||||
-Wvariadic-macros \
|
||||
-Wctor-dtor-privacy \
|
||||
-Winit-self \
|
||||
-Wstrict-null-sentinel"
|
||||
-Wvector-operation-performance \
|
||||
-Wvirtual-inheritance \
|
||||
-Wvirtual-move-assign \
|
||||
-Wvla \
|
||||
-Wvolatile-register-var \
|
||||
-Wwrite-strings \
|
||||
-Wzero-as-null-pointer-constant \
|
||||
"
|
||||
|
||||
##########################################################################
|
||||
# benchmarks
|
||||
|
@ -276,7 +440,7 @@ fuzzing-stop:
|
|||
|
||||
# call cppcheck on the main header file
|
||||
cppcheck:
|
||||
cppcheck --enable=warning --inconclusive --force --std=c++11 $(AMALGAMATED_FILE) --error-exitcode=1
|
||||
cppcheck --enable=warning --inconclusive --force --std=c++11 $(SRCS) --error-exitcode=1
|
||||
|
||||
# compile and check with Clang Static Analyzer
|
||||
clang_analyze:
|
||||
|
@ -285,6 +449,30 @@ clang_analyze:
|
|||
cd clang_analyze_build ; CCC_CXX=$(COMPILER_DIR)/clang++ CXX=$(COMPILER_DIR)/clang++ $(COMPILER_DIR)/scan-build cmake .. -GNinja
|
||||
cd clang_analyze_build ; $(COMPILER_DIR)/scan-build -enable-checker alpha.core.BoolAssignment,alpha.core.CallAndMessageUnInitRefArg,alpha.core.CastSize,alpha.core.CastToStruct,alpha.core.Conversion,alpha.core.DynamicTypeChecker,alpha.core.FixedAddr,alpha.core.PointerArithm,alpha.core.PointerSub,alpha.core.SizeofPtr,alpha.core.StackAddressAsyncEscape,alpha.core.TestAfterDivZero,alpha.deadcode.UnreachableCode,core.builtin.BuiltinFunctions,core.builtin.NoReturnFunctions,core.CallAndMessage,core.DivideZero,core.DynamicTypePropagation,core.NonnilStringConstants,core.NonNullParamChecker,core.NullDereference,core.StackAddressEscape,core.UndefinedBinaryOperatorResult,core.uninitialized.ArraySubscript,core.uninitialized.Assign,core.uninitialized.Branch,core.uninitialized.CapturedBlockVariable,core.uninitialized.UndefReturn,core.VLASize,cplusplus.InnerPointer,cplusplus.Move,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,cplusplus.SelfAssignment,deadcode.DeadStores,nullability.NullableDereferenced,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull --use-c++=$(COMPILER_DIR)/clang++ --view -analyze-headers -o clang_analyze_build/report.html ninja
|
||||
|
||||
# call cpplint (some errors expected due to false positives)
|
||||
cpplint:
|
||||
third_party/cpplint/cpplint.py --filter=-whitespace,-legal,-readability/alt_tokens,-runtime/references,-runtime/explicit --quiet --recursive include
|
||||
|
||||
clang_tidy:
|
||||
$(COMPILER_DIR)/clang-tidy $(SRCS) -- -Iinclude -std=c++11
|
||||
|
||||
pvs_studio:
|
||||
rm -fr pvs_studio_build
|
||||
mkdir pvs_studio_build
|
||||
cd pvs_studio_build ; cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=On
|
||||
cd pvs_studio_build ; pvs-studio-analyzer analyze -j 10
|
||||
cd pvs_studio_build ; plog-converter -a'GA:1,2;64:1;CS' -t fullhtml PVS-Studio.log -o pvs
|
||||
open pvs_studio_build/pvs/index.html
|
||||
|
||||
infer:
|
||||
rm -fr infer_build
|
||||
mkdir infer_build
|
||||
cd infer_build ; infer compile -- cmake .. ; infer run -- make -j 4
|
||||
|
||||
oclint:
|
||||
oclint $(SRCS) -report-type html -enable-global-analysis -o oclint_report.html -max-priority-1=10000 -max-priority-2=10000 -max-priority-3=10000 -- -std=c++11 -Iinclude
|
||||
open oclint_report.html
|
||||
|
||||
##########################################################################
|
||||
# maintainer targets
|
||||
##########################################################################
|
||||
|
|
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.
|
||||
set(JSON_BuildTests OFF CACHE INTERNAL "")
|
||||
|
||||
# If you only include this third party in PRIVATE source files, you do not
|
||||
# need to install it when your main project gets installed.
|
||||
# set(JSON_Install OFF CACHE INTERNAL "")
|
||||
|
||||
# Don't use include(nlohmann_json/CMakeLists.txt) since that carries with it
|
||||
# unintended consequences that will break the build. It's generally
|
||||
# discouraged (although not necessarily well documented as such) to use
|
||||
|
@ -155,7 +159,7 @@ If you are using [Spack](https://www.spack.io/) to manage your dependencies, you
|
|||
|
||||
If you are using [hunter](https://github.com/ruslo/hunter/) on your project for external dependencies, then you can use the [nlohmann_json package](https://docs.hunter.sh/en/latest/packages/pkg/nlohmann_json.html). Please see the hunter project for any issues regarding the packaging.
|
||||
|
||||
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo install nlohmann/json`. Please file issues [here](https://github.com/LoopPerfect/buckaroo-recipes/issues/new?title=nlohmann/nlohmann/json).
|
||||
If you are using [Buckaroo](https://buckaroo.pm), you can install this library's module with `buckaroo add github.com/buckaroo-pm/nlohmann-json`. Please file issues [here](https://github.com/buckaroo-pm/nlohmann-json). There is a demo repo [here](https://github.com/njlr/buckaroo-nholmann-json-example).
|
||||
|
||||
If you are using [vcpkg](https://github.com/Microsoft/vcpkg/) on your project for external dependencies, then you can use the [nlohmann-json package](https://github.com/Microsoft/vcpkg/tree/master/ports/nlohmann-json). Please see the vcpkg project for any issues regarding the packaging.
|
||||
|
||||
|
@ -165,6 +169,8 @@ If you are using [CocoaPods](https://cocoapods.org), you can use the library by
|
|||
|
||||
If you are using [NuGet](https://www.nuget.org), you can use the package [nlohmann.json](https://www.nuget.org/packages/nlohmann.json/). Please check [this extensive description](https://github.com/nlohmann/json/issues/1132#issuecomment-452250255) on how to use the package. Please files issues [here](https://github.com/hnkb/nlohmann-json-nuget/issues).
|
||||
|
||||
If you are using [conda](https://conda.io/), you can use the package [nlohmann_json](https://github.com/conda-forge/nlohmann_json-feedstock) from [conda-forge](https://conda-forge.org) executing `conda install -c conda-forge nlohmann_json`. Please file issues [here](https://github.com/conda-forge/nlohmann_json-feedstock/issues).
|
||||
|
||||
## Examples
|
||||
|
||||
Beside the examples below, you may want to check the [documentation](https://nlohmann.github.io/json/) where each function contains a separate code example (e.g., check out [`emplace()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a5338e282d1d02bed389d852dd670d98d.html#a5338e282d1d02bed389d852dd670d98d)). All [example files](https://github.com/nlohmann/json/tree/develop/doc/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/doc/examples/emplace.cpp)).
|
||||
|
@ -615,7 +621,7 @@ json j_patch = R"({
|
|||
})"_json;
|
||||
|
||||
// apply the patch
|
||||
j_original.merge_patch(j_patch);
|
||||
j_document.merge_patch(j_patch);
|
||||
// {
|
||||
// "a": "z",
|
||||
// "c": {
|
||||
|
@ -747,7 +753,7 @@ Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_jso
|
|||
Some important things:
|
||||
|
||||
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
|
||||
* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
|
||||
* Those methods **MUST** be available (e.g., proper headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
|
||||
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
|
||||
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
|
||||
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.
|
||||
|
@ -915,7 +921,7 @@ NLOHMANN_JSON_SERIALIZE_ENUM( TaskState, {
|
|||
{TS_STOPPED, "stopped"},
|
||||
{TS_RUNNING, "running"},
|
||||
{TS_COMPLETED, "completed"},
|
||||
});
|
||||
})
|
||||
```
|
||||
|
||||
The `NLOHMANN_JSON_SERIALIZE_ENUM()` macro declares a set of `to_json()` / `from_json()` functions for type `TaskState` while avoiding repetition and boilerplate serilization code.
|
||||
|
@ -1034,17 +1040,14 @@ The following compilers are currently used in continuous integration at [Travis]
|
|||
| Clang 4.0.1 | Ubuntu 14.04.1 LTS | clang version 4.0.1-svn305264-1~exp1 (branches/release_40) |
|
||||
| Clang 5.0.2 | Ubuntu 14.04.1 LTS | clang version 5.0.2-svn328729-1~exp1~20180509123505.100 (branches/release_50) |
|
||||
| Clang 6.0.1 | Ubuntu 14.04.1 LTS | clang version 6.0.1-svn334776-1~exp1~20180726133705.85 (branches/release_60) |
|
||||
| Clang Xcode 6.4 | OSX 10.10.5 | Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn) |
|
||||
| Clang Xcode 7.3 | OSX 10.11.6 | Apple LLVM version 7.3.0 (clang-703.0.31) |
|
||||
| Clang Xcode 8.0 | OSX 10.11.6 | Apple LLVM version 8.0.0 (clang-800.0.38) |
|
||||
| Clang Xcode 8.1 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
|
||||
| Clang Xcode 8.2 | OSX 10.12.6 | Apple LLVM version 8.0.0 (clang-800.0.42.1) |
|
||||
| Clang 7.0.1 | Ubuntu 14.04.1 LTS | clang version 7.0.1-svn348686-1~exp1~20181213084532.54 (branches/release_70) |
|
||||
| Clang Xcode 8.3 | OSX 10.11.6 | Apple LLVM version 8.1.0 (clang-802.0.38) |
|
||||
| Clang Xcode 9.0 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.37) |
|
||||
| Clang Xcode 9.1 | OSX 10.12.6 | Apple LLVM version 9.0.0 (clang-900.0.38) |
|
||||
| Clang Xcode 9.2 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.1) |
|
||||
| Clang Xcode 9.3 | OSX 10.13.3 | Apple LLVM version 9.1.0 (clang-902.0.39.2) |
|
||||
| Clang Xcode 10.0 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.2) |
|
||||
| Clang Xcode 10.1 | OSX 10.13.3 | Apple LLVM version 10.0.0 (clang-1000.11.45.5) |
|
||||
| Visual Studio 14 2015 | Windows Server 2012 R2 (x64) | Microsoft (R) Build Engine version 14.0.25420.1, MSVC 19.0.24215.1 |
|
||||
| Visual Studio 2017 | Windows Server 2016 | Microsoft (R) Build Engine version 15.7.180.61344, MSVC 19.14.26433.0 |
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.8)
|
||||
project(JSON_Benchmarks LANGUAGES CXX)
|
||||
|
||||
# set compiler flags
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Doxyfile 1.8.15
|
||||
# Doxyfile 1.8.16
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
|
@ -38,6 +38,7 @@ OPTIMIZE_OUTPUT_FOR_C = NO
|
|||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
OPTIMIZE_OUTPUT_SLICE = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
TOC_INCLUDE_HEADINGS = 0
|
||||
|
@ -141,7 +142,7 @@ USE_HTAGS = NO
|
|||
VERBATIM_HEADERS = NO
|
||||
CLANG_ASSISTED_PARSING = YES
|
||||
CLANG_OPTIONS = -std=c++11
|
||||
CLANG_COMPILATION_DATABASE_PATH = 0
|
||||
CLANG_DATABASE_PATH =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -214,6 +215,7 @@ GENERATE_LATEX = NO
|
|||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
LATEX_MAKEINDEX_CMD = \makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4
|
||||
EXTRA_PACKAGES =
|
||||
|
@ -228,6 +230,7 @@ LATEX_HIDE_INDICES = NO
|
|||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
LATEX_TIMESTAMP = NO
|
||||
LATEX_EMOJI_DIRECTORY =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
|
@ -252,6 +255,7 @@ MAN_LINKS = NO
|
|||
GENERATE_XML = YES
|
||||
XML_OUTPUT = xml
|
||||
XML_PROGRAMLISTING = YES
|
||||
XML_NS_MEMB_FILE_SCOPE = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the DOCBOOK output
|
||||
#---------------------------------------------------------------------------
|
||||
|
|
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_unsigned_t unsigned integers @endlink
|
||||
- @link nlohmann::basic_json::number_float_t floating-point @endlink
|
||||
- @link nlohmann::json_pointer JSON Pointer @endlink
|
||||
|
||||
# Container function overview
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <ciso646> // or, and, not
|
||||
#include <cmath> // signbit, isfinite
|
||||
|
@ -49,10 +50,10 @@ struct diyfp // f * 2^e
|
|||
{
|
||||
static constexpr int kPrecision = 64; // = q
|
||||
|
||||
uint64_t f = 0;
|
||||
std::uint64_t f = 0;
|
||||
int e = 0;
|
||||
|
||||
constexpr diyfp(uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
|
||||
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
|
||||
|
||||
/*!
|
||||
@brief returns x - y
|
||||
|
@ -97,23 +98,23 @@ struct diyfp // f * 2^e
|
|||
//
|
||||
// = p_lo + 2^64 p_hi
|
||||
|
||||
const uint64_t u_lo = x.f & 0xFFFFFFFF;
|
||||
const uint64_t u_hi = x.f >> 32;
|
||||
const uint64_t v_lo = y.f & 0xFFFFFFFF;
|
||||
const uint64_t v_hi = y.f >> 32;
|
||||
const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
|
||||
const std::uint64_t u_hi = x.f >> 32u;
|
||||
const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
|
||||
const std::uint64_t v_hi = y.f >> 32u;
|
||||
|
||||
const uint64_t p0 = u_lo * v_lo;
|
||||
const uint64_t p1 = u_lo * v_hi;
|
||||
const uint64_t p2 = u_hi * v_lo;
|
||||
const uint64_t p3 = u_hi * v_hi;
|
||||
const std::uint64_t p0 = u_lo * v_lo;
|
||||
const std::uint64_t p1 = u_lo * v_hi;
|
||||
const std::uint64_t p2 = u_hi * v_lo;
|
||||
const std::uint64_t p3 = u_hi * v_hi;
|
||||
|
||||
const uint64_t p0_hi = p0 >> 32;
|
||||
const uint64_t p1_lo = p1 & 0xFFFFFFFF;
|
||||
const uint64_t p1_hi = p1 >> 32;
|
||||
const uint64_t p2_lo = p2 & 0xFFFFFFFF;
|
||||
const uint64_t p2_hi = p2 >> 32;
|
||||
const std::uint64_t p0_hi = p0 >> 32u;
|
||||
const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
|
||||
const std::uint64_t p1_hi = p1 >> 32u;
|
||||
const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
|
||||
const std::uint64_t p2_hi = p2 >> 32u;
|
||||
|
||||
uint64_t Q = p0_hi + p1_lo + p2_lo;
|
||||
std::uint64_t Q = p0_hi + p1_lo + p2_lo;
|
||||
|
||||
// The full product might now be computed as
|
||||
//
|
||||
|
@ -124,9 +125,9 @@ struct diyfp // f * 2^e
|
|||
// Effectively we only need to add the highest bit in p_lo to p_hi (and
|
||||
// Q_hi + 1 does not overflow).
|
||||
|
||||
Q += uint64_t{1} << (64 - 32 - 1); // round, ties up
|
||||
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
|
||||
|
||||
const uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32);
|
||||
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
|
||||
|
||||
return {h, x.e + y.e + 64};
|
||||
}
|
||||
|
@ -139,9 +140,9 @@ struct diyfp // f * 2^e
|
|||
{
|
||||
assert(x.f != 0);
|
||||
|
||||
while ((x.f >> 63) == 0)
|
||||
while ((x.f >> 63u) == 0)
|
||||
{
|
||||
x.f <<= 1;
|
||||
x.f <<= 1u;
|
||||
x.e--;
|
||||
}
|
||||
|
||||
|
@ -195,15 +196,15 @@ boundaries compute_boundaries(FloatType value)
|
|||
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
|
||||
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
|
||||
constexpr int kMinExp = 1 - kBias;
|
||||
constexpr uint64_t kHiddenBit = uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
|
||||
constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
|
||||
|
||||
using bits_type = typename std::conditional< kPrecision == 24, uint32_t, uint64_t >::type;
|
||||
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
|
||||
|
||||
const uint64_t bits = reinterpret_bits<bits_type>(value);
|
||||
const uint64_t E = bits >> (kPrecision - 1);
|
||||
const uint64_t F = bits & (kHiddenBit - 1);
|
||||
const std::uint64_t bits = reinterpret_bits<bits_type>(value);
|
||||
const std::uint64_t E = bits >> (kPrecision - 1);
|
||||
const std::uint64_t F = bits & (kHiddenBit - 1);
|
||||
|
||||
const bool is_denormal = (E == 0);
|
||||
const bool is_denormal = E == 0;
|
||||
const diyfp v = is_denormal
|
||||
? diyfp(F, kMinExp)
|
||||
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
|
||||
|
@ -229,7 +230,7 @@ boundaries compute_boundaries(FloatType value)
|
|||
// -----------------+------+------+-------------+-------------+--- (B)
|
||||
// v- m- v m+ v+
|
||||
|
||||
const bool lower_boundary_is_closer = (F == 0 and E > 1);
|
||||
const bool lower_boundary_is_closer = F == 0 and E > 1;
|
||||
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
||||
const diyfp m_minus = lower_boundary_is_closer
|
||||
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
||||
|
@ -304,7 +305,7 @@ constexpr int kGamma = -32;
|
|||
|
||||
struct cached_power // c = f * 2^e ~= 10^k
|
||||
{
|
||||
uint64_t f;
|
||||
std::uint64_t f;
|
||||
int e;
|
||||
int k;
|
||||
};
|
||||
|
@ -368,91 +369,92 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
|||
// NB:
|
||||
// Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
|
||||
|
||||
constexpr int kCachedPowersSize = 79;
|
||||
constexpr int kCachedPowersMinDecExp = -300;
|
||||
constexpr int kCachedPowersDecStep = 8;
|
||||
|
||||
static constexpr cached_power kCachedPowers[] =
|
||||
static constexpr std::array<cached_power, 79> kCachedPowers =
|
||||
{
|
||||
{ 0xAB70FE17C79AC6CA, -1060, -300 },
|
||||
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
|
||||
{ 0xBE5691EF416BD60C, -1007, -284 },
|
||||
{ 0x8DD01FAD907FFC3C, -980, -276 },
|
||||
{ 0xD3515C2831559A83, -954, -268 },
|
||||
{ 0x9D71AC8FADA6C9B5, -927, -260 },
|
||||
{ 0xEA9C227723EE8BCB, -901, -252 },
|
||||
{ 0xAECC49914078536D, -874, -244 },
|
||||
{ 0x823C12795DB6CE57, -847, -236 },
|
||||
{ 0xC21094364DFB5637, -821, -228 },
|
||||
{ 0x9096EA6F3848984F, -794, -220 },
|
||||
{ 0xD77485CB25823AC7, -768, -212 },
|
||||
{ 0xA086CFCD97BF97F4, -741, -204 },
|
||||
{ 0xEF340A98172AACE5, -715, -196 },
|
||||
{ 0xB23867FB2A35B28E, -688, -188 },
|
||||
{ 0x84C8D4DFD2C63F3B, -661, -180 },
|
||||
{ 0xC5DD44271AD3CDBA, -635, -172 },
|
||||
{ 0x936B9FCEBB25C996, -608, -164 },
|
||||
{ 0xDBAC6C247D62A584, -582, -156 },
|
||||
{ 0xA3AB66580D5FDAF6, -555, -148 },
|
||||
{ 0xF3E2F893DEC3F126, -529, -140 },
|
||||
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
|
||||
{ 0x87625F056C7C4A8B, -475, -124 },
|
||||
{ 0xC9BCFF6034C13053, -449, -116 },
|
||||
{ 0x964E858C91BA2655, -422, -108 },
|
||||
{ 0xDFF9772470297EBD, -396, -100 },
|
||||
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
|
||||
{ 0xF8A95FCF88747D94, -343, -84 },
|
||||
{ 0xB94470938FA89BCF, -316, -76 },
|
||||
{ 0x8A08F0F8BF0F156B, -289, -68 },
|
||||
{ 0xCDB02555653131B6, -263, -60 },
|
||||
{ 0x993FE2C6D07B7FAC, -236, -52 },
|
||||
{ 0xE45C10C42A2B3B06, -210, -44 },
|
||||
{ 0xAA242499697392D3, -183, -36 },
|
||||
{ 0xFD87B5F28300CA0E, -157, -28 },
|
||||
{ 0xBCE5086492111AEB, -130, -20 },
|
||||
{ 0x8CBCCC096F5088CC, -103, -12 },
|
||||
{ 0xD1B71758E219652C, -77, -4 },
|
||||
{ 0x9C40000000000000, -50, 4 },
|
||||
{ 0xE8D4A51000000000, -24, 12 },
|
||||
{ 0xAD78EBC5AC620000, 3, 20 },
|
||||
{ 0x813F3978F8940984, 30, 28 },
|
||||
{ 0xC097CE7BC90715B3, 56, 36 },
|
||||
{ 0x8F7E32CE7BEA5C70, 83, 44 },
|
||||
{ 0xD5D238A4ABE98068, 109, 52 },
|
||||
{ 0x9F4F2726179A2245, 136, 60 },
|
||||
{ 0xED63A231D4C4FB27, 162, 68 },
|
||||
{ 0xB0DE65388CC8ADA8, 189, 76 },
|
||||
{ 0x83C7088E1AAB65DB, 216, 84 },
|
||||
{ 0xC45D1DF942711D9A, 242, 92 },
|
||||
{ 0x924D692CA61BE758, 269, 100 },
|
||||
{ 0xDA01EE641A708DEA, 295, 108 },
|
||||
{ 0xA26DA3999AEF774A, 322, 116 },
|
||||
{ 0xF209787BB47D6B85, 348, 124 },
|
||||
{ 0xB454E4A179DD1877, 375, 132 },
|
||||
{ 0x865B86925B9BC5C2, 402, 140 },
|
||||
{ 0xC83553C5C8965D3D, 428, 148 },
|
||||
{ 0x952AB45CFA97A0B3, 455, 156 },
|
||||
{ 0xDE469FBD99A05FE3, 481, 164 },
|
||||
{ 0xA59BC234DB398C25, 508, 172 },
|
||||
{ 0xF6C69A72A3989F5C, 534, 180 },
|
||||
{ 0xB7DCBF5354E9BECE, 561, 188 },
|
||||
{ 0x88FCF317F22241E2, 588, 196 },
|
||||
{ 0xCC20CE9BD35C78A5, 614, 204 },
|
||||
{ 0x98165AF37B2153DF, 641, 212 },
|
||||
{ 0xE2A0B5DC971F303A, 667, 220 },
|
||||
{ 0xA8D9D1535CE3B396, 694, 228 },
|
||||
{ 0xFB9B7CD9A4A7443C, 720, 236 },
|
||||
{ 0xBB764C4CA7A44410, 747, 244 },
|
||||
{ 0x8BAB8EEFB6409C1A, 774, 252 },
|
||||
{ 0xD01FEF10A657842C, 800, 260 },
|
||||
{ 0x9B10A4E5E9913129, 827, 268 },
|
||||
{ 0xE7109BFBA19C0C9D, 853, 276 },
|
||||
{ 0xAC2820D9623BF429, 880, 284 },
|
||||
{ 0x80444B5E7AA7CF85, 907, 292 },
|
||||
{ 0xBF21E44003ACDD2D, 933, 300 },
|
||||
{ 0x8E679C2F5E44FF8F, 960, 308 },
|
||||
{ 0xD433179D9C8CB841, 986, 316 },
|
||||
{ 0x9E19DB92B4E31BA9, 1013, 324 },
|
||||
{
|
||||
{ 0xAB70FE17C79AC6CA, -1060, -300 },
|
||||
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
|
||||
{ 0xBE5691EF416BD60C, -1007, -284 },
|
||||
{ 0x8DD01FAD907FFC3C, -980, -276 },
|
||||
{ 0xD3515C2831559A83, -954, -268 },
|
||||
{ 0x9D71AC8FADA6C9B5, -927, -260 },
|
||||
{ 0xEA9C227723EE8BCB, -901, -252 },
|
||||
{ 0xAECC49914078536D, -874, -244 },
|
||||
{ 0x823C12795DB6CE57, -847, -236 },
|
||||
{ 0xC21094364DFB5637, -821, -228 },
|
||||
{ 0x9096EA6F3848984F, -794, -220 },
|
||||
{ 0xD77485CB25823AC7, -768, -212 },
|
||||
{ 0xA086CFCD97BF97F4, -741, -204 },
|
||||
{ 0xEF340A98172AACE5, -715, -196 },
|
||||
{ 0xB23867FB2A35B28E, -688, -188 },
|
||||
{ 0x84C8D4DFD2C63F3B, -661, -180 },
|
||||
{ 0xC5DD44271AD3CDBA, -635, -172 },
|
||||
{ 0x936B9FCEBB25C996, -608, -164 },
|
||||
{ 0xDBAC6C247D62A584, -582, -156 },
|
||||
{ 0xA3AB66580D5FDAF6, -555, -148 },
|
||||
{ 0xF3E2F893DEC3F126, -529, -140 },
|
||||
{ 0xB5B5ADA8AAFF80B8, -502, -132 },
|
||||
{ 0x87625F056C7C4A8B, -475, -124 },
|
||||
{ 0xC9BCFF6034C13053, -449, -116 },
|
||||
{ 0x964E858C91BA2655, -422, -108 },
|
||||
{ 0xDFF9772470297EBD, -396, -100 },
|
||||
{ 0xA6DFBD9FB8E5B88F, -369, -92 },
|
||||
{ 0xF8A95FCF88747D94, -343, -84 },
|
||||
{ 0xB94470938FA89BCF, -316, -76 },
|
||||
{ 0x8A08F0F8BF0F156B, -289, -68 },
|
||||
{ 0xCDB02555653131B6, -263, -60 },
|
||||
{ 0x993FE2C6D07B7FAC, -236, -52 },
|
||||
{ 0xE45C10C42A2B3B06, -210, -44 },
|
||||
{ 0xAA242499697392D3, -183, -36 },
|
||||
{ 0xFD87B5F28300CA0E, -157, -28 },
|
||||
{ 0xBCE5086492111AEB, -130, -20 },
|
||||
{ 0x8CBCCC096F5088CC, -103, -12 },
|
||||
{ 0xD1B71758E219652C, -77, -4 },
|
||||
{ 0x9C40000000000000, -50, 4 },
|
||||
{ 0xE8D4A51000000000, -24, 12 },
|
||||
{ 0xAD78EBC5AC620000, 3, 20 },
|
||||
{ 0x813F3978F8940984, 30, 28 },
|
||||
{ 0xC097CE7BC90715B3, 56, 36 },
|
||||
{ 0x8F7E32CE7BEA5C70, 83, 44 },
|
||||
{ 0xD5D238A4ABE98068, 109, 52 },
|
||||
{ 0x9F4F2726179A2245, 136, 60 },
|
||||
{ 0xED63A231D4C4FB27, 162, 68 },
|
||||
{ 0xB0DE65388CC8ADA8, 189, 76 },
|
||||
{ 0x83C7088E1AAB65DB, 216, 84 },
|
||||
{ 0xC45D1DF942711D9A, 242, 92 },
|
||||
{ 0x924D692CA61BE758, 269, 100 },
|
||||
{ 0xDA01EE641A708DEA, 295, 108 },
|
||||
{ 0xA26DA3999AEF774A, 322, 116 },
|
||||
{ 0xF209787BB47D6B85, 348, 124 },
|
||||
{ 0xB454E4A179DD1877, 375, 132 },
|
||||
{ 0x865B86925B9BC5C2, 402, 140 },
|
||||
{ 0xC83553C5C8965D3D, 428, 148 },
|
||||
{ 0x952AB45CFA97A0B3, 455, 156 },
|
||||
{ 0xDE469FBD99A05FE3, 481, 164 },
|
||||
{ 0xA59BC234DB398C25, 508, 172 },
|
||||
{ 0xF6C69A72A3989F5C, 534, 180 },
|
||||
{ 0xB7DCBF5354E9BECE, 561, 188 },
|
||||
{ 0x88FCF317F22241E2, 588, 196 },
|
||||
{ 0xCC20CE9BD35C78A5, 614, 204 },
|
||||
{ 0x98165AF37B2153DF, 641, 212 },
|
||||
{ 0xE2A0B5DC971F303A, 667, 220 },
|
||||
{ 0xA8D9D1535CE3B396, 694, 228 },
|
||||
{ 0xFB9B7CD9A4A7443C, 720, 236 },
|
||||
{ 0xBB764C4CA7A44410, 747, 244 },
|
||||
{ 0x8BAB8EEFB6409C1A, 774, 252 },
|
||||
{ 0xD01FEF10A657842C, 800, 260 },
|
||||
{ 0x9B10A4E5E9913129, 827, 268 },
|
||||
{ 0xE7109BFBA19C0C9D, 853, 276 },
|
||||
{ 0xAC2820D9623BF429, 880, 284 },
|
||||
{ 0x80444B5E7AA7CF85, 907, 292 },
|
||||
{ 0xBF21E44003ACDD2D, 933, 300 },
|
||||
{ 0x8E679C2F5E44FF8F, 960, 308 },
|
||||
{ 0xD433179D9C8CB841, 986, 316 },
|
||||
{ 0x9E19DB92B4E31BA9, 1013, 324 },
|
||||
}
|
||||
};
|
||||
|
||||
// This computation gives exactly the same results for k as
|
||||
|
@ -466,10 +468,9 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
|||
|
||||
const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
|
||||
assert(index >= 0);
|
||||
assert(index < kCachedPowersSize);
|
||||
static_cast<void>(kCachedPowersSize); // Fix warning.
|
||||
assert(static_cast<std::size_t>(index) < kCachedPowers.size());
|
||||
|
||||
const cached_power cached = kCachedPowers[index];
|
||||
const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
|
||||
assert(kAlpha <= cached.e + e + 64);
|
||||
assert(kGamma >= cached.e + e + 64);
|
||||
|
||||
|
@ -480,7 +481,7 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
|||
For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
|
||||
For n == 0, returns 1 and sets pow10 := 1.
|
||||
*/
|
||||
inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
|
||||
inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
|
||||
{
|
||||
// LCOV_EXCL_START
|
||||
if (n >= 1000000000)
|
||||
|
@ -536,8 +537,8 @@ inline int find_largest_pow10(const uint32_t n, uint32_t& pow10)
|
|||
}
|
||||
}
|
||||
|
||||
inline void grisu2_round(char* buf, int len, uint64_t dist, uint64_t delta,
|
||||
uint64_t rest, uint64_t ten_k)
|
||||
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
||||
std::uint64_t rest, std::uint64_t ten_k)
|
||||
{
|
||||
assert(len >= 1);
|
||||
assert(dist <= delta);
|
||||
|
@ -598,8 +599,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
assert(M_plus.e >= kAlpha);
|
||||
assert(M_plus.e <= kGamma);
|
||||
|
||||
uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
||||
uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
||||
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
||||
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
||||
|
||||
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
|
||||
//
|
||||
|
@ -608,10 +609,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
// = ((p1 ) * 2^-e + (p2 )) * 2^e
|
||||
// = p1 + p2 * 2^e
|
||||
|
||||
const diyfp one(uint64_t{1} << -M_plus.e, M_plus.e);
|
||||
const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
|
||||
|
||||
auto p1 = static_cast<uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
|
||||
uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
||||
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
|
||||
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
||||
|
||||
// 1)
|
||||
//
|
||||
|
@ -619,7 +620,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
|
||||
assert(p1 > 0);
|
||||
|
||||
uint32_t pow10;
|
||||
std::uint32_t pow10;
|
||||
const int k = find_largest_pow10(p1, pow10);
|
||||
|
||||
// 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
|
||||
|
@ -647,8 +648,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
// M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
|
||||
// pow10 = 10^(n-1) <= p1 < 10^n
|
||||
//
|
||||
const uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
|
||||
const uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
|
||||
const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
|
||||
const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
|
||||
//
|
||||
// M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
|
||||
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
||||
|
@ -673,7 +674,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
// Note:
|
||||
// Since rest and delta share the same exponent e, it suffices to
|
||||
// compare the significands.
|
||||
const uint64_t rest = (uint64_t{p1} << -one.e) + p2;
|
||||
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
|
||||
if (rest <= delta)
|
||||
{
|
||||
// V = buffer * 10^n, with M- <= V <= M+.
|
||||
|
@ -689,7 +690,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
//
|
||||
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
|
||||
//
|
||||
const uint64_t ten_n = uint64_t{pow10} << -one.e;
|
||||
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
|
||||
grisu2_round(buffer, length, dist, delta, rest, ten_n);
|
||||
|
||||
return;
|
||||
|
@ -751,10 +752,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
// = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
|
||||
// = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
|
||||
//
|
||||
assert(p2 <= UINT64_MAX / 10);
|
||||
assert(p2 <= std::numeric_limits<std::uint64_t>::max() / 10);
|
||||
p2 *= 10;
|
||||
const uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
||||
const uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
||||
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
||||
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
||||
//
|
||||
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
|
||||
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
||||
|
@ -794,7 +795,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||
//
|
||||
// 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
|
||||
//
|
||||
const uint64_t ten_m = one.f;
|
||||
const std::uint64_t ten_m = one.f;
|
||||
grisu2_round(buffer, length, dist, delta, p2, ten_m);
|
||||
|
||||
// By construction this algorithm generates the shortest possible decimal
|
||||
|
@ -929,7 +930,7 @@ inline char* append_exponent(char* buf, int e)
|
|||
*buf++ = '+';
|
||||
}
|
||||
|
||||
auto k = static_cast<uint32_t>(e);
|
||||
auto k = static_cast<std::uint32_t>(e);
|
||||
if (k < 10)
|
||||
{
|
||||
// Always print at least two digits in the exponent.
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
#pragma once
|
||||
|
||||
#include <algorithm> // copy
|
||||
#include <ciso646> // or, and, not
|
||||
#include <iterator> // begin, end
|
||||
#include <string> // string
|
||||
#include <tuple> // tuple, get
|
||||
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
|
||||
#include <utility> // move, forward, declval, pair
|
||||
#include <valarray> // valarray
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
|
|
@ -102,12 +102,12 @@ json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F
|
|||
@liveexample{The following code shows how a `parse_error` exception can be
|
||||
caught.,parse_error}
|
||||
|
||||
@sa @ref exception for the base class of the library exceptions
|
||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa @ref type_error for exceptions indicating executing a member function with
|
||||
@sa - @ref exception for the base class of the library exceptions
|
||||
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||
a wrong type
|
||||
@sa @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa @ref other_error for exceptions indicating other library errors
|
||||
@sa - @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa - @ref other_error for exceptions indicating other library errors
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -117,7 +117,7 @@ class parse_error : public exception
|
|||
/*!
|
||||
@brief create a parse error exception
|
||||
@param[in] id_ the id of the exception
|
||||
@param[in] position the position where the error occurred (or with
|
||||
@param[in] pos the position where the error occurred (or with
|
||||
chars_read_total=0 if the position cannot be
|
||||
determined)
|
||||
@param[in] what_arg the explanatory string
|
||||
|
@ -188,12 +188,12 @@ json.exception.invalid_iterator.214 | cannot get value | Cannot get value for it
|
|||
@liveexample{The following code shows how an `invalid_iterator` exception can be
|
||||
caught.,invalid_iterator}
|
||||
|
||||
@sa @ref exception for the base class of the library exceptions
|
||||
@sa @ref parse_error for exceptions indicating a parse error
|
||||
@sa @ref type_error for exceptions indicating executing a member function with
|
||||
@sa - @ref exception for the base class of the library exceptions
|
||||
@sa - @ref parse_error for exceptions indicating a parse error
|
||||
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||
a wrong type
|
||||
@sa @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa @ref other_error for exceptions indicating other library errors
|
||||
@sa - @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa - @ref other_error for exceptions indicating other library errors
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -223,7 +223,7 @@ name / id | example message | description
|
|||
----------------------------- | --------------- | -------------------------
|
||||
json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead.
|
||||
json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types.
|
||||
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t&.
|
||||
json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &.
|
||||
json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types.
|
||||
json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types.
|
||||
json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types.
|
||||
|
@ -242,11 +242,11 @@ json.exception.type_error.317 | JSON value cannot be serialized to requested for
|
|||
@liveexample{The following code shows how a `type_error` exception can be
|
||||
caught.,type_error}
|
||||
|
||||
@sa @ref exception for the base class of the library exceptions
|
||||
@sa @ref parse_error for exceptions indicating a parse error
|
||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa @ref other_error for exceptions indicating other library errors
|
||||
@sa - @ref exception for the base class of the library exceptions
|
||||
@sa - @ref parse_error for exceptions indicating a parse error
|
||||
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa - @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa - @ref other_error for exceptions indicating other library errors
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -287,12 +287,12 @@ json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at
|
|||
@liveexample{The following code shows how an `out_of_range` exception can be
|
||||
caught.,out_of_range}
|
||||
|
||||
@sa @ref exception for the base class of the library exceptions
|
||||
@sa @ref parse_error for exceptions indicating a parse error
|
||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa @ref type_error for exceptions indicating executing a member function with
|
||||
@sa - @ref exception for the base class of the library exceptions
|
||||
@sa - @ref parse_error for exceptions indicating a parse error
|
||||
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||
a wrong type
|
||||
@sa @ref other_error for exceptions indicating other library errors
|
||||
@sa - @ref other_error for exceptions indicating other library errors
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -321,12 +321,12 @@ name / id | example message | description
|
|||
------------------------------ | --------------- | -------------------------
|
||||
json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed.
|
||||
|
||||
@sa @ref exception for the base class of the library exceptions
|
||||
@sa @ref parse_error for exceptions indicating a parse error
|
||||
@sa @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa @ref type_error for exceptions indicating executing a member function with
|
||||
@sa - @ref exception for the base class of the library exceptions
|
||||
@sa - @ref parse_error for exceptions indicating a parse error
|
||||
@sa - @ref invalid_iterator for exceptions indicating errors with iterators
|
||||
@sa - @ref type_error for exceptions indicating executing a member function with
|
||||
a wrong type
|
||||
@sa @ref out_of_range for exceptions indicating access out of the defined range
|
||||
@sa - @ref out_of_range for exceptions indicating access out of the defined range
|
||||
|
||||
@liveexample{The following code shows how an `other_error` exception can be
|
||||
caught.,other_error}
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
#include <string> // char_traits, string
|
||||
#include <utility> // make_pair, move
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
#include <nlohmann/detail/input/json_sax.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/is_sax.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
@ -52,6 +52,13 @@ class binary_reader
|
|||
assert(ia);
|
||||
}
|
||||
|
||||
// make class move-only
|
||||
binary_reader(const binary_reader&) = delete;
|
||||
binary_reader(binary_reader&&) = default;
|
||||
binary_reader& operator=(const binary_reader&) = delete;
|
||||
binary_reader& operator=(binary_reader&&) = default;
|
||||
~binary_reader() = default;
|
||||
|
||||
/*!
|
||||
@param[in] format the binary format to parse
|
||||
@param[in] sax_ a SAX event processor
|
||||
|
@ -84,10 +91,8 @@ class binary_reader
|
|||
result = parse_ubjson_internal();
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
// strict mode: next byte must be EOF
|
||||
|
@ -121,7 +126,7 @@ class binary_reader
|
|||
*/
|
||||
static constexpr bool little_endianess(int num = 1) noexcept
|
||||
{
|
||||
return (*reinterpret_cast<char*>(&num) == 1);
|
||||
return *reinterpret_cast<char*>(&num) == 1;
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -263,9 +268,9 @@ class binary_reader
|
|||
|
||||
default: // anything else not supported (yet)
|
||||
{
|
||||
char cr[3];
|
||||
(std::snprintf)(cr, sizeof(cr), "%.2hhX", static_cast<unsigned char>(element_type));
|
||||
return sax->parse_error(element_type_parse_position, std::string(cr), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr)));
|
||||
std::array<char, 3> cr{};
|
||||
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type));
|
||||
return sax->parse_error(element_type_parse_position, std::string(cr.data()), parse_error::create(114, element_type_parse_position, "Unsupported BSON record type 0x" + std::string(cr.data())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -298,12 +303,9 @@ class binary_reader
|
|||
return false;
|
||||
}
|
||||
|
||||
if (not is_array)
|
||||
if (not is_array and not sax->key(key))
|
||||
{
|
||||
if (not sax->key(key))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_UNLIKELY(not parse_bson_element_internal(element_type, element_type_parse_position)))
|
||||
|
@ -388,25 +390,25 @@ class binary_reader
|
|||
|
||||
case 0x18: // Unsigned integer (one-byte uint8_t follows)
|
||||
{
|
||||
uint8_t number;
|
||||
std::uint8_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0x19: // Unsigned integer (two-byte uint16_t follows)
|
||||
{
|
||||
uint16_t number;
|
||||
std::uint16_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0x1A: // Unsigned integer (four-byte uint32_t follows)
|
||||
{
|
||||
uint32_t number;
|
||||
std::uint32_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
|
||||
{
|
||||
uint64_t number;
|
||||
std::uint64_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
|
@ -435,29 +437,29 @@ class binary_reader
|
|||
case 0x35:
|
||||
case 0x36:
|
||||
case 0x37:
|
||||
return sax->number_integer(static_cast<int8_t>(0x20 - 1 - current));
|
||||
return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
|
||||
|
||||
case 0x38: // Negative integer (one-byte uint8_t follows)
|
||||
{
|
||||
uint8_t number;
|
||||
std::uint8_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
|
||||
}
|
||||
|
||||
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
|
||||
{
|
||||
uint16_t number;
|
||||
std::uint16_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
|
||||
}
|
||||
|
||||
case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
|
||||
{
|
||||
uint32_t number;
|
||||
std::uint32_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1) - number);
|
||||
}
|
||||
|
||||
case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
|
||||
{
|
||||
uint64_t number;
|
||||
std::uint64_t number;
|
||||
return get_number(input_format_t::cbor, number) and sax->number_integer(static_cast<number_integer_t>(-1)
|
||||
- static_cast<number_integer_t>(number));
|
||||
}
|
||||
|
@ -522,29 +524,29 @@ class binary_reader
|
|||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
return get_cbor_array(static_cast<std::size_t>(current & 0x1F));
|
||||
return get_cbor_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
|
||||
|
||||
case 0x98: // array (one-byte uint8_t for n follows)
|
||||
{
|
||||
uint8_t len;
|
||||
std::uint8_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0x99: // array (two-byte uint16_t for n follow)
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0x9A: // array (four-byte uint32_t for n follow)
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0x9B: // array (eight-byte uint64_t for n follow)
|
||||
{
|
||||
uint64_t len;
|
||||
std::uint64_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
|
@ -576,29 +578,29 @@ class binary_reader
|
|||
case 0xB5:
|
||||
case 0xB6:
|
||||
case 0xB7:
|
||||
return get_cbor_object(static_cast<std::size_t>(current & 0x1F));
|
||||
return get_cbor_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu));
|
||||
|
||||
case 0xB8: // map (one-byte uint8_t for n follows)
|
||||
{
|
||||
uint8_t len;
|
||||
std::uint8_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xB9: // map (two-byte uint16_t for n follow)
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xBA: // map (four-byte uint32_t for n follow)
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xBB: // map (eight-byte uint64_t for n follow)
|
||||
{
|
||||
uint64_t len;
|
||||
std::uint64_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_cbor_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
|
@ -638,11 +640,11 @@ class binary_reader
|
|||
// without such support. An example of a small decoder for
|
||||
// half-precision floating-point numbers in the C language
|
||||
// is shown in Fig. 3.
|
||||
const int half = (byte1 << 8) + byte2;
|
||||
const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
|
||||
const double val = [&half]
|
||||
{
|
||||
const int exp = (half >> 10) & 0x1F;
|
||||
const int mant = half & 0x3FF;
|
||||
const int exp = (half >> 10u) & 0x1Fu;
|
||||
const unsigned int mant = half & 0x3FFu;
|
||||
assert(0 <= exp and exp <= 32);
|
||||
assert(0 <= mant and mant <= 1024);
|
||||
switch (exp)
|
||||
|
@ -657,7 +659,7 @@ class binary_reader
|
|||
return std::ldexp(mant + 1024, exp - 25);
|
||||
}
|
||||
}();
|
||||
return sax->number_float((half & 0x8000) != 0
|
||||
return sax->number_float((half & 0x8000u) != 0
|
||||
? static_cast<number_float_t>(-val)
|
||||
: static_cast<number_float_t>(val), "");
|
||||
}
|
||||
|
@ -728,30 +730,30 @@ class binary_reader
|
|||
case 0x76:
|
||||
case 0x77:
|
||||
{
|
||||
return get_string(input_format_t::cbor, current & 0x1F, result);
|
||||
return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
|
||||
}
|
||||
|
||||
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
|
||||
{
|
||||
uint8_t len;
|
||||
std::uint8_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
|
||||
{
|
||||
uint64_t len;
|
||||
std::uint64_t len;
|
||||
return get_number(input_format_t::cbor, len) and get_string(input_format_t::cbor, len, result);
|
||||
}
|
||||
|
||||
|
@ -1026,7 +1028,7 @@ class binary_reader
|
|||
case 0x8D:
|
||||
case 0x8E:
|
||||
case 0x8F:
|
||||
return get_msgpack_object(static_cast<std::size_t>(current & 0x0F));
|
||||
return get_msgpack_object(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
|
||||
|
||||
// fixarray
|
||||
case 0x90:
|
||||
|
@ -1045,7 +1047,7 @@ class binary_reader
|
|||
case 0x9D:
|
||||
case 0x9E:
|
||||
case 0x9F:
|
||||
return get_msgpack_array(static_cast<std::size_t>(current & 0x0F));
|
||||
return get_msgpack_array(static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
|
||||
|
||||
// fixstr
|
||||
case 0xA0:
|
||||
|
@ -1108,49 +1110,49 @@ class binary_reader
|
|||
|
||||
case 0xCC: // uint 8
|
||||
{
|
||||
uint8_t number;
|
||||
std::uint8_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0xCD: // uint 16
|
||||
{
|
||||
uint16_t number;
|
||||
std::uint16_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0xCE: // uint 32
|
||||
{
|
||||
uint32_t number;
|
||||
std::uint32_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0xCF: // uint 64
|
||||
{
|
||||
uint64_t number;
|
||||
std::uint64_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 0xD0: // int 8
|
||||
{
|
||||
int8_t number;
|
||||
std::int8_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 0xD1: // int 16
|
||||
{
|
||||
int16_t number;
|
||||
std::int16_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 0xD2: // int 32
|
||||
{
|
||||
int32_t number;
|
||||
std::int32_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 0xD3: // int 64
|
||||
{
|
||||
int64_t number;
|
||||
std::int64_t number;
|
||||
return get_number(input_format_t::msgpack, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
|
@ -1164,25 +1166,25 @@ class binary_reader
|
|||
|
||||
case 0xDC: // array 16
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xDD: // array 32
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_msgpack_array(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xDE: // map 16
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
case 0xDF: // map 32
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_msgpack_object(static_cast<std::size_t>(len));
|
||||
}
|
||||
|
||||
|
@ -1219,7 +1221,7 @@ class binary_reader
|
|||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
return sax->number_integer(static_cast<int8_t>(current));
|
||||
return sax->number_integer(static_cast<std::int8_t>(current));
|
||||
|
||||
default: // anything else
|
||||
{
|
||||
|
@ -1282,24 +1284,24 @@ class binary_reader
|
|||
case 0xBE:
|
||||
case 0xBF:
|
||||
{
|
||||
return get_string(input_format_t::msgpack, current & 0x1F, result);
|
||||
return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
|
||||
}
|
||||
|
||||
case 0xD9: // str 8
|
||||
{
|
||||
uint8_t len;
|
||||
std::uint8_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
|
||||
}
|
||||
|
||||
case 0xDA: // str 16
|
||||
{
|
||||
uint16_t len;
|
||||
std::uint16_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
|
||||
}
|
||||
|
||||
case 0xDB: // str 32
|
||||
{
|
||||
uint32_t len;
|
||||
std::uint32_t len;
|
||||
return get_number(input_format_t::msgpack, len) and get_string(input_format_t::msgpack, len, result);
|
||||
}
|
||||
|
||||
|
@ -1397,7 +1399,7 @@ class binary_reader
|
|||
{
|
||||
if (get_char)
|
||||
{
|
||||
get(); // TODO: may we ignore N here?
|
||||
get(); // TODO(niels): may we ignore N here?
|
||||
}
|
||||
|
||||
if (JSON_UNLIKELY(not unexpect_eof(input_format_t::ubjson, "value")))
|
||||
|
@ -1409,31 +1411,31 @@ class binary_reader
|
|||
{
|
||||
case 'U':
|
||||
{
|
||||
uint8_t len;
|
||||
std::uint8_t len;
|
||||
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
int8_t len;
|
||||
std::int8_t len;
|
||||
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
int16_t len;
|
||||
std::int16_t len;
|
||||
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
int32_t len;
|
||||
std::int32_t len;
|
||||
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
int64_t len;
|
||||
std::int64_t len;
|
||||
return get_number(input_format_t::ubjson, len) and get_string(input_format_t::ubjson, len, result);
|
||||
}
|
||||
|
||||
|
@ -1453,7 +1455,7 @@ class binary_reader
|
|||
{
|
||||
case 'U':
|
||||
{
|
||||
uint8_t number;
|
||||
std::uint8_t number;
|
||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1464,7 +1466,7 @@ class binary_reader
|
|||
|
||||
case 'i':
|
||||
{
|
||||
int8_t number;
|
||||
std::int8_t number;
|
||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1475,7 +1477,7 @@ class binary_reader
|
|||
|
||||
case 'I':
|
||||
{
|
||||
int16_t number;
|
||||
std::int16_t number;
|
||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1486,7 +1488,7 @@ class binary_reader
|
|||
|
||||
case 'l':
|
||||
{
|
||||
int32_t number;
|
||||
std::int32_t number;
|
||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1497,7 +1499,7 @@ class binary_reader
|
|||
|
||||
case 'L':
|
||||
{
|
||||
int64_t number;
|
||||
std::int64_t number;
|
||||
if (JSON_UNLIKELY(not get_number(input_format_t::ubjson, number)))
|
||||
{
|
||||
return false;
|
||||
|
@ -1552,10 +1554,12 @@ class binary_reader
|
|||
|
||||
return get_ubjson_size_value(result.first);
|
||||
}
|
||||
else if (current == '#')
|
||||
|
||||
if (current == '#')
|
||||
{
|
||||
return get_ubjson_size_value(result.first);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1580,31 +1584,31 @@ class binary_reader
|
|||
|
||||
case 'U':
|
||||
{
|
||||
uint8_t number;
|
||||
std::uint8_t number;
|
||||
return get_number(input_format_t::ubjson, number) and sax->number_unsigned(number);
|
||||
}
|
||||
|
||||
case 'i':
|
||||
{
|
||||
int8_t number;
|
||||
std::int8_t number;
|
||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 'I':
|
||||
{
|
||||
int16_t number;
|
||||
std::int16_t number;
|
||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 'l':
|
||||
{
|
||||
int32_t number;
|
||||
std::int32_t number;
|
||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
case 'L':
|
||||
{
|
||||
int64_t number;
|
||||
std::int64_t number;
|
||||
return get_number(input_format_t::ubjson, number) and sax->number_integer(number);
|
||||
}
|
||||
|
||||
|
@ -1809,7 +1813,7 @@ class binary_reader
|
|||
int get()
|
||||
{
|
||||
++chars_read;
|
||||
return (current = ia->get_character());
|
||||
return current = ia->get_character();
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1843,7 +1847,7 @@ class binary_reader
|
|||
bool get_number(const input_format_t format, NumberType& result)
|
||||
{
|
||||
// step 1: read input into array with system's byte order
|
||||
std::array<uint8_t, sizeof(NumberType)> vec;
|
||||
std::array<std::uint8_t, sizeof(NumberType)> vec;
|
||||
for (std::size_t i = 0; i < sizeof(NumberType); ++i)
|
||||
{
|
||||
get();
|
||||
|
@ -1853,13 +1857,13 @@ class binary_reader
|
|||
}
|
||||
|
||||
// reverse byte order prior to conversion if necessary
|
||||
if (is_little_endian && !InputIsLittleEndian)
|
||||
if (is_little_endian != InputIsLittleEndian)
|
||||
{
|
||||
vec[sizeof(NumberType) - i - 1] = static_cast<uint8_t>(current);
|
||||
vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec[i] = static_cast<uint8_t>(current); // LCOV_EXCL_LINE
|
||||
vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1920,9 +1924,9 @@ class binary_reader
|
|||
*/
|
||||
std::string get_token_string() const
|
||||
{
|
||||
char cr[3];
|
||||
(std::snprintf)(cr, 3, "%.2hhX", static_cast<unsigned char>(current));
|
||||
return std::string{cr};
|
||||
std::array<char, 3> cr{};
|
||||
(std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current));
|
||||
return std::string{cr.data()};
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1955,10 +1959,8 @@ class binary_reader
|
|||
error_msg += "BSON";
|
||||
break;
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
return error_msg + " " + context + ": " + detail;
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdio> //FILE *
|
||||
#include <cstring> // strlen
|
||||
#include <istream> // istream
|
||||
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
||||
|
@ -10,7 +12,6 @@
|
|||
#include <string> // string, char_traits
|
||||
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
||||
#include <utility> // pair, declval
|
||||
#include <cstdio> //FILE *
|
||||
|
||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
@ -58,10 +59,18 @@ class file_input_adapter : public input_adapter_protocol
|
|||
: m_file(f)
|
||||
{}
|
||||
|
||||
// make class move-only
|
||||
file_input_adapter(const file_input_adapter&) = delete;
|
||||
file_input_adapter(file_input_adapter&&) = default;
|
||||
file_input_adapter& operator=(const file_input_adapter&) = delete;
|
||||
file_input_adapter& operator=(file_input_adapter&&) = default;
|
||||
~file_input_adapter() override = default;
|
||||
|
||||
std::char_traits<char>::int_type get_character() noexcept override
|
||||
{
|
||||
return std::fgetc(m_file);
|
||||
}
|
||||
|
||||
private:
|
||||
/// the file pointer to read from
|
||||
std::FILE* m_file;
|
||||
|
@ -153,7 +162,11 @@ template<typename WideStringType, size_t T>
|
|||
struct wide_string_input_helper
|
||||
{
|
||||
// UTF-32
|
||||
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
|
||||
static void fill_buffer(const WideStringType& str,
|
||||
size_t& current_wchar,
|
||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
||||
size_t& utf8_bytes_index,
|
||||
size_t& utf8_bytes_filled)
|
||||
{
|
||||
utf8_bytes_index = 0;
|
||||
|
||||
|
@ -165,39 +178,39 @@ struct wide_string_input_helper
|
|||
else
|
||||
{
|
||||
// get the current character
|
||||
const auto wc = static_cast<int>(str[current_wchar++]);
|
||||
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
|
||||
|
||||
// UTF-32 to UTF-8 encoding
|
||||
if (wc < 0x80)
|
||||
{
|
||||
utf8_bytes[0] = wc;
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||
utf8_bytes_filled = 1;
|
||||
}
|
||||
else if (wc <= 0x7FF)
|
||||
{
|
||||
utf8_bytes[0] = 0xC0 | ((wc >> 6) & 0x1F);
|
||||
utf8_bytes[1] = 0x80 | (wc & 0x3F);
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u) & 0x1Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes_filled = 2;
|
||||
}
|
||||
else if (wc <= 0xFFFF)
|
||||
{
|
||||
utf8_bytes[0] = 0xE0 | ((wc >> 12) & 0x0F);
|
||||
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
|
||||
utf8_bytes[2] = 0x80 | (wc & 0x3F);
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u) & 0x0Fu));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes_filled = 3;
|
||||
}
|
||||
else if (wc <= 0x10FFFF)
|
||||
{
|
||||
utf8_bytes[0] = 0xF0 | ((wc >> 18) & 0x07);
|
||||
utf8_bytes[1] = 0x80 | ((wc >> 12) & 0x3F);
|
||||
utf8_bytes[2] = 0x80 | ((wc >> 6) & 0x3F);
|
||||
utf8_bytes[3] = 0x80 | (wc & 0x3F);
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((wc >> 18u) & 0x07u));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 12u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes_filled = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown character
|
||||
utf8_bytes[0] = wc;
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||
utf8_bytes_filled = 1;
|
||||
}
|
||||
}
|
||||
|
@ -208,7 +221,11 @@ template<typename WideStringType>
|
|||
struct wide_string_input_helper<WideStringType, 2>
|
||||
{
|
||||
// UTF-16
|
||||
static void fill_buffer(const WideStringType& str, size_t& current_wchar, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
|
||||
static void fill_buffer(const WideStringType& str,
|
||||
size_t& current_wchar,
|
||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
||||
size_t& utf8_bytes_index,
|
||||
size_t& utf8_bytes_filled)
|
||||
{
|
||||
utf8_bytes_index = 0;
|
||||
|
||||
|
@ -220,44 +237,44 @@ struct wide_string_input_helper<WideStringType, 2>
|
|||
else
|
||||
{
|
||||
// get the current character
|
||||
const auto wc = static_cast<int>(str[current_wchar++]);
|
||||
const auto wc = static_cast<unsigned int>(str[current_wchar++]);
|
||||
|
||||
// UTF-16 to UTF-8 encoding
|
||||
if (wc < 0x80)
|
||||
{
|
||||
utf8_bytes[0] = wc;
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||
utf8_bytes_filled = 1;
|
||||
}
|
||||
else if (wc <= 0x7FF)
|
||||
{
|
||||
utf8_bytes[0] = 0xC0 | ((wc >> 6));
|
||||
utf8_bytes[1] = 0x80 | (wc & 0x3F);
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((wc >> 6u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes_filled = 2;
|
||||
}
|
||||
else if (0xD800 > wc or wc >= 0xE000)
|
||||
{
|
||||
utf8_bytes[0] = 0xE0 | ((wc >> 12));
|
||||
utf8_bytes[1] = 0x80 | ((wc >> 6) & 0x3F);
|
||||
utf8_bytes[2] = 0x80 | (wc & 0x3F);
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((wc >> 12u)));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((wc >> 6u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (wc & 0x3Fu));
|
||||
utf8_bytes_filled = 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (current_wchar < str.size())
|
||||
{
|
||||
const auto wc2 = static_cast<int>(str[current_wchar++]);
|
||||
const int charcode = 0x10000 + (((wc & 0x3FF) << 10) | (wc2 & 0x3FF));
|
||||
utf8_bytes[0] = 0xf0 | (charcode >> 18);
|
||||
utf8_bytes[1] = 0x80 | ((charcode >> 12) & 0x3F);
|
||||
utf8_bytes[2] = 0x80 | ((charcode >> 6) & 0x3F);
|
||||
utf8_bytes[3] = 0x80 | (charcode & 0x3F);
|
||||
const auto wc2 = static_cast<unsigned int>(str[current_wchar++]);
|
||||
const auto charcode = 0x10000u + (((wc & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
|
||||
utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
|
||||
utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
|
||||
utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
|
||||
utf8_bytes_filled = 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
// unknown character
|
||||
++current_wchar;
|
||||
utf8_bytes[0] = wc;
|
||||
utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
|
||||
utf8_bytes_filled = 1;
|
||||
}
|
||||
}
|
||||
|
@ -269,7 +286,7 @@ template<typename WideStringType>
|
|||
class wide_string_input_adapter : public input_adapter_protocol
|
||||
{
|
||||
public:
|
||||
explicit wide_string_input_adapter(const WideStringType& w) noexcept
|
||||
explicit wide_string_input_adapter(const WideStringType& w) noexcept
|
||||
: str(w)
|
||||
{}
|
||||
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cassert> // assert
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
@ -158,6 +159,13 @@ class json_sax_dom_parser
|
|||
: root(r), allow_exceptions(allow_exceptions_)
|
||||
{}
|
||||
|
||||
// make class move-only
|
||||
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
|
||||
json_sax_dom_parser(json_sax_dom_parser&&) = default;
|
||||
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
|
||||
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default;
|
||||
~json_sax_dom_parser() = default;
|
||||
|
||||
bool null()
|
||||
{
|
||||
handle_value(nullptr);
|
||||
|
@ -249,16 +257,16 @@ class json_sax_dom_parser
|
|||
switch ((ex.id / 100) % 100)
|
||||
{
|
||||
case 1:
|
||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||
case 4:
|
||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
||||
// LCOV_EXCL_START
|
||||
case 2:
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||
case 3:
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
|
@ -295,18 +303,17 @@ class json_sax_dom_parser
|
|||
ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
|
||||
return &(ref_stack.back()->m_value.array->back());
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(object_element);
|
||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||
return object_element;
|
||||
}
|
||||
|
||||
assert(ref_stack.back()->is_object())
|
||||
assert(object_element);
|
||||
*object_element = BasicJsonType(std::forward<Value>(v));
|
||||
return object_element;
|
||||
}
|
||||
|
||||
/// the parsed JSON value
|
||||
BasicJsonType& root;
|
||||
/// stack to model hierarchy of values
|
||||
std::vector<BasicJsonType*> ref_stack;
|
||||
std::vector<BasicJsonType*> ref_stack {};
|
||||
/// helper to hold the reference for the next object element
|
||||
BasicJsonType* object_element = nullptr;
|
||||
/// whether a syntax error occurred
|
||||
|
@ -334,6 +341,13 @@ class json_sax_dom_callback_parser
|
|||
keep_stack.push_back(true);
|
||||
}
|
||||
|
||||
// make class move-only
|
||||
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
|
||||
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default;
|
||||
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
|
||||
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default;
|
||||
~json_sax_dom_callback_parser() = default;
|
||||
|
||||
bool null()
|
||||
{
|
||||
handle_value(nullptr);
|
||||
|
@ -380,13 +394,9 @@ class json_sax_dom_callback_parser
|
|||
ref_stack.push_back(val.second);
|
||||
|
||||
// check object limit
|
||||
if (ref_stack.back())
|
||||
if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
{
|
||||
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408,
|
||||
"excessive object size: " + std::to_string(len)));
|
||||
}
|
||||
JSON_THROW(out_of_range::create(408, "excessive object size: " + std::to_string(len)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -411,13 +421,10 @@ class json_sax_dom_callback_parser
|
|||
|
||||
bool end_object()
|
||||
{
|
||||
if (ref_stack.back())
|
||||
if (ref_stack.back() and not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
||||
{
|
||||
if (not callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
|
||||
{
|
||||
// discard object
|
||||
*ref_stack.back() = discarded;
|
||||
}
|
||||
// discard object
|
||||
*ref_stack.back() = discarded;
|
||||
}
|
||||
|
||||
assert(not ref_stack.empty());
|
||||
|
@ -425,18 +432,15 @@ class json_sax_dom_callback_parser
|
|||
ref_stack.pop_back();
|
||||
keep_stack.pop_back();
|
||||
|
||||
if (not ref_stack.empty() and ref_stack.back())
|
||||
if (not ref_stack.empty() and ref_stack.back() and ref_stack.back()->is_object())
|
||||
{
|
||||
// remove discarded value
|
||||
if (ref_stack.back()->is_object())
|
||||
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
|
||||
{
|
||||
for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
|
||||
if (it->is_discarded())
|
||||
{
|
||||
if (it->is_discarded())
|
||||
{
|
||||
ref_stack.back()->erase(it);
|
||||
break;
|
||||
}
|
||||
ref_stack.back()->erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -453,13 +457,9 @@ class json_sax_dom_callback_parser
|
|||
ref_stack.push_back(val.second);
|
||||
|
||||
// check array limit
|
||||
if (ref_stack.back())
|
||||
if (ref_stack.back() and JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
{
|
||||
if (JSON_UNLIKELY(len != std::size_t(-1) and len > ref_stack.back()->max_size()))
|
||||
{
|
||||
JSON_THROW(out_of_range::create(408,
|
||||
"excessive array size: " + std::to_string(len)));
|
||||
}
|
||||
JSON_THROW(out_of_range::create(408, "excessive array size: " + std::to_string(len)));
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -485,12 +485,9 @@ class json_sax_dom_callback_parser
|
|||
keep_stack.pop_back();
|
||||
|
||||
// remove discarded value
|
||||
if (not keep and not ref_stack.empty())
|
||||
if (not keep and not ref_stack.empty() and ref_stack.back()->is_array())
|
||||
{
|
||||
if (ref_stack.back()->is_array())
|
||||
{
|
||||
ref_stack.back()->m_value.array->pop_back();
|
||||
}
|
||||
ref_stack.back()->m_value.array->pop_back();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -506,16 +503,16 @@ class json_sax_dom_callback_parser
|
|||
switch ((ex.id / 100) % 100)
|
||||
{
|
||||
case 1:
|
||||
JSON_THROW(*reinterpret_cast<const detail::parse_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::parse_error*>(&ex));
|
||||
case 4:
|
||||
JSON_THROW(*reinterpret_cast<const detail::out_of_range*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::out_of_range*>(&ex));
|
||||
// LCOV_EXCL_START
|
||||
case 2:
|
||||
JSON_THROW(*reinterpret_cast<const detail::invalid_iterator*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::invalid_iterator*>(&ex));
|
||||
case 3:
|
||||
JSON_THROW(*reinterpret_cast<const detail::type_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::type_error*>(&ex));
|
||||
case 5:
|
||||
JSON_THROW(*reinterpret_cast<const detail::other_error*>(&ex));
|
||||
JSON_THROW(*static_cast<const detail::other_error*>(&ex));
|
||||
default:
|
||||
assert(false);
|
||||
// LCOV_EXCL_STOP
|
||||
|
@ -585,37 +582,38 @@ class json_sax_dom_callback_parser
|
|||
// we now only expect arrays and objects
|
||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
||||
|
||||
// array
|
||||
if (ref_stack.back()->is_array())
|
||||
{
|
||||
ref_stack.back()->m_value.array->push_back(std::move(value));
|
||||
return {true, &(ref_stack.back()->m_value.array->back())};
|
||||
}
|
||||
else
|
||||
|
||||
// object
|
||||
assert(ref_stack.back()->is_object())
|
||||
// check if we should store an element for the current key
|
||||
assert(not key_keep_stack.empty());
|
||||
const bool store_element = key_keep_stack.back();
|
||||
key_keep_stack.pop_back();
|
||||
|
||||
if (not store_element)
|
||||
{
|
||||
// check if we should store an element for the current key
|
||||
assert(not key_keep_stack.empty());
|
||||
const bool store_element = key_keep_stack.back();
|
||||
key_keep_stack.pop_back();
|
||||
|
||||
if (not store_element)
|
||||
{
|
||||
return {false, nullptr};
|
||||
}
|
||||
|
||||
assert(object_element);
|
||||
*object_element = std::move(value);
|
||||
return {true, object_element};
|
||||
return {false, nullptr};
|
||||
}
|
||||
|
||||
assert(object_element);
|
||||
*object_element = std::move(value);
|
||||
return {true, object_element};
|
||||
}
|
||||
|
||||
/// the parsed JSON value
|
||||
BasicJsonType& root;
|
||||
/// stack to model hierarchy of values
|
||||
std::vector<BasicJsonType*> ref_stack;
|
||||
std::vector<BasicJsonType*> ref_stack {};
|
||||
/// stack to manage which values to keep
|
||||
std::vector<bool> keep_stack;
|
||||
std::vector<bool> keep_stack {};
|
||||
/// stack to manage which object keys to keep
|
||||
std::vector<bool> key_keep_stack;
|
||||
std::vector<bool> key_keep_stack {};
|
||||
/// helper to hold the reference for the next object element
|
||||
BasicJsonType* object_element = nullptr;
|
||||
/// whether a syntax error occurred
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
#pragma once
|
||||
|
||||
#include <array> // array
|
||||
#include <clocale> // localeconv
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
||||
#include <cstdio> // snprintf
|
||||
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
||||
#include <initializer_list> // initializer_list
|
||||
#include <string> // char_traits, string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
#include <nlohmann/detail/input/position_t.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
@ -148,22 +150,22 @@ class lexer
|
|||
assert(current == 'u');
|
||||
int codepoint = 0;
|
||||
|
||||
const auto factors = { 12, 8, 4, 0 };
|
||||
const auto factors = { 12u, 8u, 4u, 0u };
|
||||
for (const auto factor : factors)
|
||||
{
|
||||
get();
|
||||
|
||||
if (current >= '0' and current <= '9')
|
||||
{
|
||||
codepoint += ((current - 0x30) << factor);
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
|
||||
}
|
||||
else if (current >= 'A' and current <= 'F')
|
||||
{
|
||||
codepoint += ((current - 0x37) << factor);
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
|
||||
}
|
||||
else if (current >= 'a' and current <= 'f')
|
||||
{
|
||||
codepoint += ((current - 0x57) << factor);
|
||||
codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -321,15 +323,15 @@ class lexer
|
|||
if (JSON_LIKELY(0xDC00 <= codepoint2 and codepoint2 <= 0xDFFF))
|
||||
{
|
||||
// overwrite codepoint
|
||||
codepoint =
|
||||
// high surrogate occupies the most significant 22 bits
|
||||
(codepoint1 << 10)
|
||||
// low surrogate occupies the least significant 15 bits
|
||||
+ codepoint2
|
||||
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
||||
// in the result so we have to subtract with:
|
||||
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
||||
- 0x35FDC00;
|
||||
codepoint = static_cast<int>(
|
||||
// high surrogate occupies the most significant 22 bits
|
||||
(static_cast<unsigned int>(codepoint1) << 10u)
|
||||
// low surrogate occupies the least significant 15 bits
|
||||
+ static_cast<unsigned int>(codepoint2)
|
||||
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
||||
// in the result so we have to subtract with:
|
||||
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
||||
- 0x35FDC00u);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -364,23 +366,23 @@ class lexer
|
|||
else if (codepoint <= 0x7FF)
|
||||
{
|
||||
// 2-byte characters: 110xxxxx 10xxxxxx
|
||||
add(0xC0 | (codepoint >> 6));
|
||||
add(0x80 | (codepoint & 0x3F));
|
||||
add(static_cast<int>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
else if (codepoint <= 0xFFFF)
|
||||
{
|
||||
// 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
|
||||
add(0xE0 | (codepoint >> 12));
|
||||
add(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
add(0x80 | (codepoint & 0x3F));
|
||||
add(static_cast<int>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
add(0xF0 | (codepoint >> 18));
|
||||
add(0x80 | ((codepoint >> 12) & 0x3F));
|
||||
add(0x80 | ((codepoint >> 6) & 0x3F));
|
||||
add(0x80 | (codepoint & 0x3F));
|
||||
add(static_cast<int>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
|
||||
add(static_cast<int>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -906,13 +908,9 @@ class lexer
|
|||
goto scan_number_any1;
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
{
|
||||
// all other characters are rejected outside scan_number()
|
||||
assert(false);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
// all other characters are rejected outside scan_number()
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
|
||||
scan_number_minus:
|
||||
|
@ -1297,7 +1295,7 @@ scan_number_done:
|
|||
|
||||
if (JSON_LIKELY(current != std::char_traits<char>::eof()))
|
||||
{
|
||||
assert(token_string.size() != 0);
|
||||
assert(not token_string.empty());
|
||||
token_string.pop_back();
|
||||
}
|
||||
}
|
||||
|
@ -1359,9 +1357,9 @@ scan_number_done:
|
|||
if ('\x00' <= c and c <= '\x1F')
|
||||
{
|
||||
// escape control characters
|
||||
char cs[9];
|
||||
(std::snprintf)(cs, 9, "<U+%.4X>", static_cast<unsigned char>(c));
|
||||
result += cs;
|
||||
std::array<char, 9> cs{};
|
||||
(std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c));
|
||||
result += cs.data();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1483,7 +1481,7 @@ scan_number_done:
|
|||
bool next_unget = false;
|
||||
|
||||
/// the start position of the current token
|
||||
position_t position;
|
||||
position_t position {};
|
||||
|
||||
/// raw input token string (for error messages)
|
||||
std::vector<char> token_string {};
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
#include <functional> // function
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/is_sax.hpp>
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
#include <nlohmann/detail/input/json_sax.hpp>
|
||||
#include <nlohmann/detail/input/lexer.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/is_sax.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
|
@ -458,7 +459,7 @@ class parser
|
|||
/// get next token from lexer
|
||||
token_type get_token()
|
||||
{
|
||||
return (last_token = m_lexer.scan());
|
||||
return last_token = m_lexer.scan();
|
||||
}
|
||||
|
||||
std::string exception_message(const token_type expected, const std::string& context)
|
||||
|
|
|
@ -23,5 +23,5 @@ struct position_t
|
|||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
|
|
@ -607,7 +607,7 @@ class iter_impl
|
|||
/// associated JSON instance
|
||||
pointer m_object = nullptr;
|
||||
/// the actual iterator of the associated instance
|
||||
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it;
|
||||
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
|
||||
};
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
} // namespace nlohmann
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef> // size_t
|
||||
#include <string> // string, to_string
|
||||
#include <iterator> // input_iterator_tag
|
||||
#include <string> // string, to_string
|
||||
#include <tuple> // tuple_size, get, tuple_element
|
||||
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
@ -147,6 +147,11 @@ auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decl
|
|||
// And see https://github.com/nlohmann/json/pull/1391
|
||||
namespace std
|
||||
{
|
||||
#if defined(__clang__)
|
||||
// Fix: https://github.com/nlohmann/json/issues/1401
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||
#endif
|
||||
template <typename IteratorType>
|
||||
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>>
|
||||
: public std::integral_constant<std::size_t, 2> {};
|
||||
|
@ -159,4 +164,7 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
|
|||
get<N>(std::declval <
|
||||
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
|
||||
};
|
||||
}
|
||||
#if defined(__clang__)
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
} // namespace std
|
||||
|
|
|
@ -45,5 +45,5 @@ struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>> {
|
|||
using pointer = T*;
|
||||
using reference = T&;
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
} // namespace nlohmann
|
||||
|
|
|
@ -4,10 +4,11 @@
|
|||
#include <cassert> // assert
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string
|
||||
#include <utility> // move
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
|
@ -76,6 +77,139 @@ class json_pointer
|
|||
return to_string();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief append another JSON pointer at the end of this JSON pointer
|
||||
*/
|
||||
json_pointer& operator/=(const json_pointer& ptr)
|
||||
{
|
||||
reference_tokens.insert(reference_tokens.end(),
|
||||
ptr.reference_tokens.begin(),
|
||||
ptr.reference_tokens.end());
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @copydoc push_back(std::string&&)
|
||||
json_pointer& operator/=(std::string token)
|
||||
{
|
||||
push_back(std::move(token));
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// @copydoc operator/=(std::string)
|
||||
json_pointer& operator/=(std::size_t array_index)
|
||||
{
|
||||
return *this /= std::to_string(array_index);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||
*/
|
||||
friend json_pointer operator/(const json_pointer& left_ptr,
|
||||
const json_pointer& right_ptr)
|
||||
{
|
||||
return json_pointer(left_ptr) /= right_ptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
|
||||
*/
|
||||
friend json_pointer operator/(const json_pointer& ptr, std::string token)
|
||||
{
|
||||
return json_pointer(ptr) /= std::move(token);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
|
||||
*/
|
||||
friend json_pointer operator/(const json_pointer& lhs, std::size_t array_index)
|
||||
{
|
||||
return json_pointer(lhs) /= array_index;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief returns the parent of this JSON pointer
|
||||
|
||||
@return parent of this JSON pointer; in case this JSON pointer is the root,
|
||||
the root itself is returned
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example shows the result of `parent_pointer` for different
|
||||
JSON Pointers.,json_pointer__parent_pointer}
|
||||
|
||||
@since version 3.6.0
|
||||
*/
|
||||
json_pointer parent_pointer() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
json_pointer res = *this;
|
||||
res.pop_back();
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief remove and return last reference token
|
||||
@throw out_of_range.405 if JSON pointer has no parent
|
||||
*/
|
||||
std::string pop_back()
|
||||
{
|
||||
if (JSON_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
}
|
||||
|
||||
auto last = reference_tokens.back();
|
||||
reference_tokens.pop_back();
|
||||
return last;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief append an unescaped token at the end of the reference pointer
|
||||
|
||||
@param[in] token token to add
|
||||
|
||||
@complexity Amortized constant.
|
||||
|
||||
@liveexample{The example shows the result of `push_back` for different
|
||||
JSON Pointers.,json_pointer__push_back}
|
||||
|
||||
@since version 0.6.0
|
||||
*/
|
||||
void push_back(const std::string& token)
|
||||
{
|
||||
reference_tokens.push_back(token);
|
||||
}
|
||||
|
||||
/// @copydoc push_back(const std::string&)
|
||||
void push_back(std::string&& token)
|
||||
{
|
||||
reference_tokens.push_back(std::move(token));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return whether pointer points to the root document
|
||||
|
||||
@return true iff the JSON pointer points to the root document
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this function never throws exceptions.
|
||||
|
||||
@liveexample{The example shows the result of `empty` for different JSON
|
||||
Pointers.,json_pointer__empty}
|
||||
|
||||
@since version 3.6.0
|
||||
*/
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return reference_tokens.empty();
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
@param[in] s reference token to be converted into an array index
|
||||
|
||||
|
@ -97,32 +231,9 @@ class json_pointer
|
|||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
@brief remove and return last reference pointer
|
||||
@throw out_of_range.405 if JSON pointer has no parent
|
||||
*/
|
||||
std::string pop_back()
|
||||
{
|
||||
if (JSON_UNLIKELY(is_root()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
}
|
||||
|
||||
auto last = reference_tokens.back();
|
||||
reference_tokens.pop_back();
|
||||
return last;
|
||||
}
|
||||
|
||||
/// return whether pointer points to the root document
|
||||
bool is_root() const noexcept
|
||||
{
|
||||
return reference_tokens.empty();
|
||||
}
|
||||
|
||||
json_pointer top() const
|
||||
{
|
||||
if (JSON_UNLIKELY(is_root()))
|
||||
if (JSON_UNLIKELY(empty()))
|
||||
{
|
||||
JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent"));
|
||||
}
|
||||
|
@ -233,7 +344,7 @@ class json_pointer
|
|||
std::all_of(reference_token.begin(), reference_token.end(),
|
||||
[](const char x)
|
||||
{
|
||||
return (x >= '0' and x <= '9');
|
||||
return x >= '0' and x <= '9';
|
||||
});
|
||||
|
||||
// change value to array for numbers or "-" or to object otherwise
|
||||
|
@ -682,7 +793,7 @@ class json_pointer
|
|||
friend bool operator==(json_pointer const& lhs,
|
||||
json_pointer const& rhs) noexcept
|
||||
{
|
||||
return (lhs.reference_tokens == rhs.reference_tokens);
|
||||
return lhs.reference_tokens == rhs.reference_tokens;
|
||||
}
|
||||
|
||||
friend bool operator!=(json_pointer const& lhs,
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <utility> // pair
|
||||
|
||||
// This file contains all internal macro definitions
|
||||
// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
|
||||
|
||||
|
@ -37,6 +39,19 @@
|
|||
#define JSON_DEPRECATED
|
||||
#endif
|
||||
|
||||
// allow for portable nodiscard warnings
|
||||
#if defined(__has_cpp_attribute)
|
||||
#if __has_cpp_attribute(nodiscard)
|
||||
#define JSON_NODISCARD [[nodiscard]]
|
||||
#elif __has_cpp_attribute(gnu::warn_unused_result)
|
||||
#define JSON_NODISCARD [[gnu::warn_unused_result]]
|
||||
#else
|
||||
#define JSON_NODISCARD
|
||||
#endif
|
||||
#else
|
||||
#define JSON_NODISCARD
|
||||
#endif
|
||||
|
||||
// allow to disable exceptions
|
||||
#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
|
||||
#define JSON_THROW(exception) throw exception
|
||||
|
@ -44,6 +59,7 @@
|
|||
#define JSON_CATCH(exception) catch(exception)
|
||||
#define JSON_INTERNAL_CATCH(exception) catch(exception)
|
||||
#else
|
||||
#include <cstdlib>
|
||||
#define JSON_THROW(exception) std::abort()
|
||||
#define JSON_TRY if(true)
|
||||
#define JSON_CATCH(exception) if(false)
|
||||
|
@ -72,8 +88,8 @@
|
|||
|
||||
// manual branch prediction
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
#define JSON_LIKELY(x) __builtin_expect(!!(x), 1)
|
||||
#define JSON_UNLIKELY(x) __builtin_expect(!!(x), 0)
|
||||
#define JSON_LIKELY(x) __builtin_expect(static_cast<bool>(x), 1)
|
||||
#define JSON_UNLIKELY(x) __builtin_expect(static_cast<bool>(x), 0)
|
||||
#else
|
||||
#define JSON_LIKELY(x) x
|
||||
#define JSON_UNLIKELY(x) x
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#undef JSON_LIKELY
|
||||
#undef JSON_UNLIKELY
|
||||
#undef JSON_DEPRECATED
|
||||
#undef JSON_NODISCARD
|
||||
#undef JSON_HAS_CPP_14
|
||||
#undef JSON_HAS_CPP_17
|
||||
#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||
|
|
|
@ -14,7 +14,9 @@ struct nonesuch
|
|||
nonesuch() = delete;
|
||||
~nonesuch() = delete;
|
||||
nonesuch(nonesuch const&) = delete;
|
||||
nonesuch(nonesuch const&&) = delete;
|
||||
void operator=(nonesuch const&) = delete;
|
||||
void operator=(nonesuch&&) = delete;
|
||||
};
|
||||
|
||||
template <class Default,
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <cstdint> // size_t
|
||||
#include <utility> // declval
|
||||
#include <string> // string
|
||||
|
||||
#include <nlohmann/detail/meta/detected.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
|
|
|
@ -5,11 +5,11 @@
|
|||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||
#include <utility> // declval
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/detected.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
||||
#include <cstring> // memcpy
|
||||
#include <limits> // numeric_limits
|
||||
#include <string> // string
|
||||
|
||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
||||
|
@ -87,27 +88,27 @@ class binary_writer
|
|||
// code from the value_t::number_unsigned case here.
|
||||
if (j.m_value.number_integer <= 0x17)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x18));
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x19));
|
||||
write_number(static_cast<uint16_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x1A));
|
||||
write_number(static_cast<uint32_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x1B));
|
||||
write_number(static_cast<uint64_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -117,27 +118,27 @@ class binary_writer
|
|||
const auto positive_number = -1 - j.m_value.number_integer;
|
||||
if (j.m_value.number_integer >= -24)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0x20 + positive_number));
|
||||
write_number(static_cast<std::uint8_t>(0x20 + positive_number));
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x38));
|
||||
write_number(static_cast<uint8_t>(positive_number));
|
||||
write_number(static_cast<std::uint8_t>(positive_number));
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x39));
|
||||
write_number(static_cast<uint16_t>(positive_number));
|
||||
write_number(static_cast<std::uint16_t>(positive_number));
|
||||
}
|
||||
else if (positive_number <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x3A));
|
||||
write_number(static_cast<uint32_t>(positive_number));
|
||||
write_number(static_cast<std::uint32_t>(positive_number));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x3B));
|
||||
write_number(static_cast<uint64_t>(positive_number));
|
||||
write_number(static_cast<std::uint64_t>(positive_number));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -147,27 +148,27 @@ class binary_writer
|
|||
{
|
||||
if (j.m_value.number_unsigned <= 0x17)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x18));
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x19));
|
||||
write_number(static_cast<uint16_t>(j.m_value.number_unsigned));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x1A));
|
||||
write_number(static_cast<uint32_t>(j.m_value.number_unsigned));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
else
|
||||
{
|
||||
oa->write_character(to_char_type(0x1B));
|
||||
write_number(static_cast<uint64_t>(j.m_value.number_unsigned));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -185,28 +186,28 @@ class binary_writer
|
|||
const auto N = j.m_value.string->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0x60 + N));
|
||||
write_number(static_cast<std::uint8_t>(0x60 + N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x78));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x79));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x7A));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<uint64_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x7B));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
|
@ -223,28 +224,28 @@ class binary_writer
|
|||
const auto N = j.m_value.array->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0x80 + N));
|
||||
write_number(static_cast<std::uint8_t>(0x80 + N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x98));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x99));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x9A));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<uint64_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0x9B));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
|
@ -262,28 +263,28 @@ class binary_writer
|
|||
const auto N = j.m_value.object->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
write_number(static_cast<uint8_t>(0xA0 + N));
|
||||
write_number(static_cast<std::uint8_t>(0xA0 + N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xB8));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xB9));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xBA));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else if (N <= (std::numeric_limits<uint64_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
oa->write_character(to_char_type(0xBB));
|
||||
write_number(static_cast<uint64_t>(N));
|
||||
write_number(static_cast<std::uint64_t>(N));
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
|
@ -332,31 +333,31 @@ class binary_writer
|
|||
if (j.m_value.number_unsigned < 128)
|
||||
{
|
||||
// positive fixnum
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// uint 8
|
||||
oa->write_character(to_char_type(0xCC));
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// uint 16
|
||||
oa->write_character(to_char_type(0xCD));
|
||||
write_number(static_cast<uint16_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// uint 32
|
||||
oa->write_character(to_char_type(0xCE));
|
||||
write_number(static_cast<uint32_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
// uint 64
|
||||
oa->write_character(to_char_type(0xCF));
|
||||
write_number(static_cast<uint64_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -364,35 +365,35 @@ class binary_writer
|
|||
if (j.m_value.number_integer >= -32)
|
||||
{
|
||||
// negative fixnum
|
||||
write_number(static_cast<int8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<int8_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
// int 8
|
||||
oa->write_character(to_char_type(0xD0));
|
||||
write_number(static_cast<int8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::int8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<int16_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
// int 16
|
||||
oa->write_character(to_char_type(0xD1));
|
||||
write_number(static_cast<int16_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::int16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<int32_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
// int 32
|
||||
oa->write_character(to_char_type(0xD2));
|
||||
write_number(static_cast<int32_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::int32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<int64_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<int64_t>::max)())
|
||||
else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() and
|
||||
j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
// int 64
|
||||
oa->write_character(to_char_type(0xD3));
|
||||
write_number(static_cast<int64_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::int64_t>(j.m_value.number_integer));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -403,31 +404,31 @@ class binary_writer
|
|||
if (j.m_value.number_unsigned < 128)
|
||||
{
|
||||
// positive fixnum
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// uint 8
|
||||
oa->write_character(to_char_type(0xCC));
|
||||
write_number(static_cast<uint8_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// uint 16
|
||||
oa->write_character(to_char_type(0xCD));
|
||||
write_number(static_cast<uint16_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// uint 32
|
||||
oa->write_character(to_char_type(0xCE));
|
||||
write_number(static_cast<uint32_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
|
||||
}
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<uint64_t>::max)())
|
||||
else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
|
||||
{
|
||||
// uint 64
|
||||
oa->write_character(to_char_type(0xCF));
|
||||
write_number(static_cast<uint64_t>(j.m_value.number_integer));
|
||||
write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -446,25 +447,25 @@ class binary_writer
|
|||
if (N <= 31)
|
||||
{
|
||||
// fixstr
|
||||
write_number(static_cast<uint8_t>(0xA0 | N));
|
||||
write_number(static_cast<std::uint8_t>(0xA0 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
// str 8
|
||||
oa->write_character(to_char_type(0xD9));
|
||||
write_number(static_cast<uint8_t>(N));
|
||||
write_number(static_cast<std::uint8_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// str 16
|
||||
oa->write_character(to_char_type(0xDA));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// str 32
|
||||
oa->write_character(to_char_type(0xDB));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write the string
|
||||
|
@ -481,19 +482,19 @@ class binary_writer
|
|||
if (N <= 15)
|
||||
{
|
||||
// fixarray
|
||||
write_number(static_cast<uint8_t>(0x90 | N));
|
||||
write_number(static_cast<std::uint8_t>(0x90 | N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// array 16
|
||||
oa->write_character(to_char_type(0xDC));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// array 32
|
||||
oa->write_character(to_char_type(0xDD));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write each element
|
||||
|
@ -511,19 +512,19 @@ class binary_writer
|
|||
if (N <= 15)
|
||||
{
|
||||
// fixmap
|
||||
write_number(static_cast<uint8_t>(0x80 | (N & 0xF)));
|
||||
write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint16_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||
{
|
||||
// map 16
|
||||
oa->write_character(to_char_type(0xDE));
|
||||
write_number(static_cast<uint16_t>(N));
|
||||
write_number(static_cast<std::uint16_t>(N));
|
||||
}
|
||||
else if (N <= (std::numeric_limits<uint32_t>::max)())
|
||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||
{
|
||||
// map 32
|
||||
oa->write_character(to_char_type(0xDF));
|
||||
write_number(static_cast<uint32_t>(N));
|
||||
write_number(static_cast<std::uint32_t>(N));
|
||||
}
|
||||
|
||||
// step 2: write each element
|
||||
|
@ -789,14 +790,9 @@ class binary_writer
|
|||
*/
|
||||
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
||||
{
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
return sizeof(std::int32_t);
|
||||
}
|
||||
else
|
||||
{
|
||||
return sizeof(std::int64_t);
|
||||
}
|
||||
return (std::numeric_limits<std::int32_t>::min)() <= value and value <= (std::numeric_limits<std::int32_t>::max)()
|
||||
? sizeof(std::int32_t)
|
||||
: sizeof(std::int64_t);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -1064,45 +1060,45 @@ class binary_writer
|
|||
void write_number_with_ubjson_prefix(const NumberType n,
|
||||
const bool add_prefix)
|
||||
{
|
||||
if (n <= static_cast<uint64_t>((std::numeric_limits<int8_t>::max)()))
|
||||
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('i')); // int8
|
||||
}
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
else if (n <= (std::numeric_limits<uint8_t>::max)())
|
||||
else if (n <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('U')); // uint8
|
||||
}
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
else if (n <= static_cast<uint64_t>((std::numeric_limits<int16_t>::max)()))
|
||||
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('I')); // int16
|
||||
}
|
||||
write_number(static_cast<int16_t>(n));
|
||||
write_number(static_cast<std::int16_t>(n));
|
||||
}
|
||||
else if (n <= static_cast<uint64_t>((std::numeric_limits<int32_t>::max)()))
|
||||
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('l')); // int32
|
||||
}
|
||||
write_number(static_cast<int32_t>(n));
|
||||
write_number(static_cast<std::int32_t>(n));
|
||||
}
|
||||
else if (n <= static_cast<uint64_t>((std::numeric_limits<int64_t>::max)()))
|
||||
else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('L')); // int64
|
||||
}
|
||||
write_number(static_cast<int64_t>(n));
|
||||
write_number(static_cast<std::int64_t>(n));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1117,45 +1113,45 @@ class binary_writer
|
|||
void write_number_with_ubjson_prefix(const NumberType n,
|
||||
const bool add_prefix)
|
||||
{
|
||||
if ((std::numeric_limits<int8_t>::min)() <= n and n <= (std::numeric_limits<int8_t>::max)())
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= n and n <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('i')); // int8
|
||||
}
|
||||
write_number(static_cast<int8_t>(n));
|
||||
write_number(static_cast<std::int8_t>(n));
|
||||
}
|
||||
else if (static_cast<int64_t>((std::numeric_limits<uint8_t>::min)()) <= n and n <= static_cast<int64_t>((std::numeric_limits<uint8_t>::max)()))
|
||||
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n and n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('U')); // uint8
|
||||
}
|
||||
write_number(static_cast<uint8_t>(n));
|
||||
write_number(static_cast<std::uint8_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<int16_t>::min)() <= n and n <= (std::numeric_limits<int16_t>::max)())
|
||||
else if ((std::numeric_limits<std::int16_t>::min)() <= n and n <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('I')); // int16
|
||||
}
|
||||
write_number(static_cast<int16_t>(n));
|
||||
write_number(static_cast<std::int16_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<int32_t>::min)() <= n and n <= (std::numeric_limits<int32_t>::max)())
|
||||
else if ((std::numeric_limits<std::int32_t>::min)() <= n and n <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('l')); // int32
|
||||
}
|
||||
write_number(static_cast<int32_t>(n));
|
||||
write_number(static_cast<std::int32_t>(n));
|
||||
}
|
||||
else if ((std::numeric_limits<int64_t>::min)() <= n and n <= (std::numeric_limits<int64_t>::max)())
|
||||
else if ((std::numeric_limits<std::int64_t>::min)() <= n and n <= (std::numeric_limits<std::int64_t>::max)())
|
||||
{
|
||||
if (add_prefix)
|
||||
{
|
||||
oa->write_character(to_char_type('L')); // int64
|
||||
}
|
||||
write_number(static_cast<int64_t>(n));
|
||||
write_number(static_cast<std::int64_t>(n));
|
||||
}
|
||||
// LCOV_EXCL_START
|
||||
else
|
||||
|
@ -1186,19 +1182,19 @@ class binary_writer
|
|||
|
||||
case value_t::number_integer:
|
||||
{
|
||||
if ((std::numeric_limits<int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int8_t>::max)())
|
||||
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
return 'i';
|
||||
}
|
||||
if ((std::numeric_limits<uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<uint8_t>::max)())
|
||||
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
return 'U';
|
||||
}
|
||||
if ((std::numeric_limits<int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int16_t>::max)())
|
||||
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
return 'I';
|
||||
}
|
||||
if ((std::numeric_limits<int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<int32_t>::max)())
|
||||
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
return 'l';
|
||||
}
|
||||
|
@ -1208,19 +1204,19 @@ class binary_writer
|
|||
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<int8_t>::max)())
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int8_t>::max)())
|
||||
{
|
||||
return 'i';
|
||||
}
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<uint8_t>::max)())
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
|
||||
{
|
||||
return 'U';
|
||||
}
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<int16_t>::max)())
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int16_t>::max)())
|
||||
{
|
||||
return 'I';
|
||||
}
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<int32_t>::max)())
|
||||
if (j.m_value.number_unsigned <= (std::numeric_limits<std::int32_t>::max)())
|
||||
{
|
||||
return 'l';
|
||||
}
|
||||
|
@ -1278,7 +1274,7 @@ class binary_writer
|
|||
std::memcpy(vec.data(), &n, sizeof(NumberType));
|
||||
|
||||
// step 2: write array to output (with possible reordering)
|
||||
if (is_little_endian and not OutputIsLittleEndian)
|
||||
if (is_little_endian != OutputIsLittleEndian)
|
||||
{
|
||||
// reverse byte order prior to conversion if necessary
|
||||
std::reverse(vec.begin(), vec.end());
|
||||
|
|
|
@ -12,9 +12,10 @@
|
|||
#include <limits> // numeric_limits
|
||||
#include <string> // string
|
||||
#include <type_traits> // is_same
|
||||
#include <utility> // move
|
||||
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/output/binary_writer.hpp>
|
||||
|
@ -44,8 +45,8 @@ class serializer
|
|||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
static constexpr uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr uint8_t UTF8_REJECT = 1;
|
||||
static constexpr std::uint8_t UTF8_ACCEPT = 0;
|
||||
static constexpr std::uint8_t UTF8_REJECT = 1;
|
||||
|
||||
public:
|
||||
/*!
|
||||
|
@ -277,6 +278,9 @@ class serializer
|
|||
o->write_characters("null", 4);
|
||||
return;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,8 +301,8 @@ class serializer
|
|||
*/
|
||||
void dump_escaped(const string_t& s, const bool ensure_ascii)
|
||||
{
|
||||
uint32_t codepoint;
|
||||
uint8_t state = UTF8_ACCEPT;
|
||||
std::uint32_t codepoint;
|
||||
std::uint8_t state = UTF8_ACCEPT;
|
||||
std::size_t bytes = 0; // number of bytes written to string_buffer
|
||||
|
||||
// number of bytes written at the point of the last valid byte
|
||||
|
@ -373,14 +377,14 @@ class serializer
|
|||
if (codepoint <= 0xFFFF)
|
||||
{
|
||||
(std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
||||
static_cast<uint16_t>(codepoint));
|
||||
static_cast<std::uint16_t>(codepoint));
|
||||
bytes += 6;
|
||||
}
|
||||
else
|
||||
{
|
||||
(std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
||||
static_cast<uint16_t>(0xD7C0 + (codepoint >> 10)),
|
||||
static_cast<uint16_t>(0xDC00 + (codepoint & 0x3FF)));
|
||||
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
||||
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu)));
|
||||
bytes += 12;
|
||||
}
|
||||
}
|
||||
|
@ -454,6 +458,16 @@ class serializer
|
|||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
|
||||
string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
|
||||
}
|
||||
|
||||
// write buffer and reset index; there must be 13 bytes
|
||||
// left, as this is the maximal number of bytes to be
|
||||
// written ("\uxxxx\uxxxx\0") for one code point
|
||||
if (string_buffer.size() - bytes < 13)
|
||||
{
|
||||
o->write_characters(string_buffer.data(), bytes);
|
||||
bytes = 0;
|
||||
}
|
||||
|
||||
bytes_after_last_accept = bytes;
|
||||
}
|
||||
|
||||
|
@ -463,6 +477,9 @@ class serializer
|
|||
state = UTF8_ACCEPT;
|
||||
break;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -497,7 +514,7 @@ class serializer
|
|||
case error_handler_t::strict:
|
||||
{
|
||||
std::string sn(3, '\0');
|
||||
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<uint8_t>(s.back()));
|
||||
(std::snprintf)(&sn[0], sn.size(), "%.2X", static_cast<std::uint8_t>(s.back()));
|
||||
JSON_THROW(type_error::create(316, "incomplete UTF-8 string; last byte: 0x" + sn));
|
||||
}
|
||||
|
||||
|
@ -523,6 +540,9 @@ class serializer
|
|||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -579,16 +599,16 @@ class serializer
|
|||
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
|
||||
{
|
||||
{
|
||||
{'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'}, {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'},
|
||||
{'1', '0'}, {'1', '1'}, {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'}, {'1', '8'}, {'1', '9'},
|
||||
{'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'}, {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
|
||||
{'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'}, {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'},
|
||||
{'4', '0'}, {'4', '1'}, {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'}, {'4', '8'}, {'4', '9'},
|
||||
{'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'}, {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
|
||||
{'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'}, {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'},
|
||||
{'7', '0'}, {'7', '1'}, {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'}, {'7', '8'}, {'7', '9'},
|
||||
{'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'}, {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
|
||||
{'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'},
|
||||
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
|
||||
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
|
||||
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
|
||||
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
|
||||
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
|
||||
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
|
||||
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
|
||||
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
|
||||
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
|
||||
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -600,7 +620,7 @@ class serializer
|
|||
}
|
||||
|
||||
// use a pointer to fill the buffer
|
||||
auto buffer_ptr = begin(number_buffer);
|
||||
auto buffer_ptr = number_buffer.begin();
|
||||
|
||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value and not(x >= 0); // see issue #755
|
||||
number_unsigned_t abs_value;
|
||||
|
@ -610,7 +630,7 @@ class serializer
|
|||
if (is_negative)
|
||||
{
|
||||
*buffer_ptr = '-';
|
||||
abs_value = static_cast<number_unsigned_t>(0 - x);
|
||||
abs_value = static_cast<number_unsigned_t>(std::abs(static_cast<std::intmax_t>(x)));
|
||||
|
||||
// account one more byte for the minus sign
|
||||
n_chars = 1 + count_digits(abs_value);
|
||||
|
@ -630,7 +650,6 @@ class serializer
|
|||
|
||||
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
|
||||
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
|
||||
const auto buffer_end = buffer_ptr;
|
||||
while (abs_value >= 100)
|
||||
{
|
||||
const auto digits_index = static_cast<unsigned>((abs_value % 100));
|
||||
|
@ -730,7 +749,7 @@ class serializer
|
|||
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
||||
[](char c)
|
||||
{
|
||||
return (c == '.' or c == 'e');
|
||||
return c == '.' or c == 'e';
|
||||
});
|
||||
|
||||
if (value_is_int_like)
|
||||
|
@ -760,9 +779,9 @@ class serializer
|
|||
@copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
|
||||
@sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
|
||||
*/
|
||||
static uint8_t decode(uint8_t& state, uint32_t& codep, const uint8_t byte) noexcept
|
||||
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
|
||||
{
|
||||
static const std::array<uint8_t, 400> utf8d =
|
||||
static const std::array<std::uint8_t, 400> utf8d =
|
||||
{
|
||||
{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
|
||||
|
@ -782,11 +801,11 @@ class serializer
|
|||
}
|
||||
};
|
||||
|
||||
const uint8_t type = utf8d[byte];
|
||||
const std::uint8_t type = utf8d[byte];
|
||||
|
||||
codep = (state != UTF8_ACCEPT)
|
||||
? (byte & 0x3fu) | (codep << 6)
|
||||
: static_cast<uint32_t>(0xff >> type) & (byte);
|
||||
? (byte & 0x3fu) | (codep << 6u)
|
||||
: (0xFFu >> type) & (byte);
|
||||
|
||||
state = utf8d[256u + state * 16u + type];
|
||||
return state;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <ciso646> // and
|
||||
#include <cstddef> // size_t
|
||||
#include <cstdint> // uint8_t
|
||||
#include <string> // string
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
|
|
|
@ -27,8 +27,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NLOHMANN_JSON_HPP
|
||||
#define NLOHMANN_JSON_HPP
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_HPP_
|
||||
|
||||
#define NLOHMANN_JSON_VERSION_MAJOR 3
|
||||
#define NLOHMANN_JSON_VERSION_MINOR 5
|
||||
|
@ -42,33 +42,35 @@ SOFTWARE.
|
|||
#include <initializer_list> // initializer_list
|
||||
#include <iosfwd> // istream, ostream
|
||||
#include <iterator> // random_access_iterator_tag
|
||||
#include <memory> // unique_ptr
|
||||
#include <numeric> // accumulate
|
||||
#include <string> // string, stoi, to_string
|
||||
#include <utility> // declval, forward, move, pair, swap
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
#include <nlohmann/adl_serializer.hpp>
|
||||
#include <nlohmann/detail/conversions/from_json.hpp>
|
||||
#include <nlohmann/detail/conversions/to_json.hpp>
|
||||
#include <nlohmann/detail/exceptions.hpp>
|
||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||
#include <nlohmann/detail/input/lexer.hpp>
|
||||
#include <nlohmann/detail/input/parser.hpp>
|
||||
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
|
||||
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
||||
#include <nlohmann/detail/iterators/iter_impl.hpp>
|
||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||
#include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
|
||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||
#include <nlohmann/detail/output/binary_writer.hpp>
|
||||
#include <nlohmann/detail/output/serializer.hpp>
|
||||
#include <nlohmann/detail/json_ref.hpp>
|
||||
#include <nlohmann/detail/iterators/primitive_iterator.hpp>
|
||||
#include <nlohmann/detail/json_pointer.hpp>
|
||||
#include <nlohmann/adl_serializer.hpp>
|
||||
#include <nlohmann/detail/json_ref.hpp>
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
#include <nlohmann/detail/output/binary_writer.hpp>
|
||||
#include <nlohmann/detail/output/output_adapters.hpp>
|
||||
#include <nlohmann/detail/output/serializer.hpp>
|
||||
#include <nlohmann/detail/value_t.hpp>
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
|
@ -317,6 +319,7 @@ class basic_json
|
|||
|
||||
@since 2.1.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json meta()
|
||||
{
|
||||
basic_json result;
|
||||
|
@ -1322,6 +1325,8 @@ class basic_json
|
|||
case value_t::discarded:
|
||||
m_type = value_t::discarded;
|
||||
break;
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
assert_invariant();
|
||||
}
|
||||
|
@ -1409,7 +1414,7 @@ class basic_json
|
|||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||
[](const detail::json_ref<basic_json>& element_ref)
|
||||
{
|
||||
return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
|
||||
return element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string();
|
||||
});
|
||||
|
||||
// adjust type if type deduction is not wanted
|
||||
|
@ -1489,6 +1494,7 @@ class basic_json
|
|||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json array(initializer_list_t init = {})
|
||||
{
|
||||
return basic_json(init, false, value_t::array);
|
||||
|
@ -1532,6 +1538,7 @@ class basic_json
|
|||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json object(initializer_list_t init = {})
|
||||
{
|
||||
return basic_json(init, false, value_t::object);
|
||||
|
@ -2092,7 +2099,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_null() const noexcept
|
||||
{
|
||||
return (m_type == value_t::null);
|
||||
return m_type == value_t::null;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2114,7 +2121,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_boolean() const noexcept
|
||||
{
|
||||
return (m_type == value_t::boolean);
|
||||
return m_type == value_t::boolean;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2173,7 +2180,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_number_integer() const noexcept
|
||||
{
|
||||
return (m_type == value_t::number_integer or m_type == value_t::number_unsigned);
|
||||
return m_type == value_t::number_integer or m_type == value_t::number_unsigned;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2201,7 +2208,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_number_unsigned() const noexcept
|
||||
{
|
||||
return (m_type == value_t::number_unsigned);
|
||||
return m_type == value_t::number_unsigned;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2229,7 +2236,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_number_float() const noexcept
|
||||
{
|
||||
return (m_type == value_t::number_float);
|
||||
return m_type == value_t::number_float;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2251,7 +2258,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_object() const noexcept
|
||||
{
|
||||
return (m_type == value_t::object);
|
||||
return m_type == value_t::object;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2273,7 +2280,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_array() const noexcept
|
||||
{
|
||||
return (m_type == value_t::array);
|
||||
return m_type == value_t::array;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2295,7 +2302,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_string() const noexcept
|
||||
{
|
||||
return (m_type == value_t::string);
|
||||
return m_type == value_t::string;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2322,7 +2329,7 @@ class basic_json
|
|||
*/
|
||||
constexpr bool is_discarded() const noexcept
|
||||
{
|
||||
return (m_type == value_t::discarded);
|
||||
return m_type == value_t::discarded;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -2856,7 +2863,7 @@ class basic_json
|
|||
|
||||
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
|
||||
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
|
||||
#if defined(JSON_HAS_CPP_17) && defined(_MSC_VER) and _MSC_VER <= 1914
|
||||
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
|
||||
and not std::is_same<ValueType, typename std::string_view>::value
|
||||
#endif
|
||||
#endif
|
||||
|
@ -3894,6 +3901,8 @@ class basic_json
|
|||
|
||||
@liveexample{The example shows how `find()` is used.,find__key_type}
|
||||
|
||||
@sa @ref contains(KeyT&&) const -- checks whether a key exists
|
||||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
template<typename KeyT>
|
||||
|
@ -3954,6 +3963,36 @@ class basic_json
|
|||
return is_object() ? m_value.object->count(std::forward<KeyT>(key)) : 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief check the existence of an element in a JSON object
|
||||
|
||||
Check whether an element exists in a JSON object with key equivalent to
|
||||
@a key. If the element is not found or the JSON value is not an object,
|
||||
false is returned.
|
||||
|
||||
@note This method always returns false when executed on a JSON type
|
||||
that is not an object.
|
||||
|
||||
@param[in] key key value to check its existence.
|
||||
|
||||
@return true if an element with specified @a key exists. If no such
|
||||
element with such key is found or the JSON value is not an object,
|
||||
false is returned.
|
||||
|
||||
@complexity Logarithmic in the size of the JSON object.
|
||||
|
||||
@liveexample{The following code shows an example for `contains()`.,contains}
|
||||
|
||||
@sa @ref find(KeyT&&) -- returns an iterator to an object element
|
||||
|
||||
@since version 3.6.0
|
||||
*/
|
||||
template<typename KeyT>
|
||||
bool contains(KeyT&& key) const
|
||||
{
|
||||
return is_object() and m_value.object->find(std::forward<KeyT>(key)) != m_value.object->end();
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
|
@ -5530,28 +5569,28 @@ class basic_json
|
|||
switch (lhs_type)
|
||||
{
|
||||
case value_t::array:
|
||||
return (*lhs.m_value.array == *rhs.m_value.array);
|
||||
return *lhs.m_value.array == *rhs.m_value.array;
|
||||
|
||||
case value_t::object:
|
||||
return (*lhs.m_value.object == *rhs.m_value.object);
|
||||
return *lhs.m_value.object == *rhs.m_value.object;
|
||||
|
||||
case value_t::null:
|
||||
return true;
|
||||
|
||||
case value_t::string:
|
||||
return (*lhs.m_value.string == *rhs.m_value.string);
|
||||
return *lhs.m_value.string == *rhs.m_value.string;
|
||||
|
||||
case value_t::boolean:
|
||||
return (lhs.m_value.boolean == rhs.m_value.boolean);
|
||||
return lhs.m_value.boolean == rhs.m_value.boolean;
|
||||
|
||||
case value_t::number_integer:
|
||||
return (lhs.m_value.number_integer == rhs.m_value.number_integer);
|
||||
return lhs.m_value.number_integer == rhs.m_value.number_integer;
|
||||
|
||||
case value_t::number_unsigned:
|
||||
return (lhs.m_value.number_unsigned == rhs.m_value.number_unsigned);
|
||||
return lhs.m_value.number_unsigned == rhs.m_value.number_unsigned;
|
||||
|
||||
case value_t::number_float:
|
||||
return (lhs.m_value.number_float == rhs.m_value.number_float);
|
||||
return lhs.m_value.number_float == rhs.m_value.number_float;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -5559,27 +5598,27 @@ class basic_json
|
|||
}
|
||||
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_float)
|
||||
{
|
||||
return (static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float);
|
||||
return static_cast<number_float_t>(lhs.m_value.number_integer) == rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_integer)
|
||||
{
|
||||
return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer));
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_float)
|
||||
{
|
||||
return (static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float);
|
||||
return static_cast<number_float_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_float;
|
||||
}
|
||||
else if (lhs_type == value_t::number_float and rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return (lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned));
|
||||
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
else if (lhs_type == value_t::number_unsigned and rhs_type == value_t::number_integer)
|
||||
{
|
||||
return (static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer);
|
||||
return static_cast<number_integer_t>(lhs.m_value.number_unsigned) == rhs.m_value.number_integer;
|
||||
}
|
||||
else if (lhs_type == value_t::number_integer and rhs_type == value_t::number_unsigned)
|
||||
{
|
||||
return (lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned));
|
||||
return lhs.m_value.number_integer == static_cast<number_integer_t>(rhs.m_value.number_unsigned);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -5593,7 +5632,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator==(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs == basic_json(rhs));
|
||||
return lhs == basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5604,7 +5643,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator==(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) == rhs);
|
||||
return basic_json(lhs) == rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5638,7 +5677,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator!=(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs != basic_json(rhs));
|
||||
return lhs != basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5649,7 +5688,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator!=(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) != rhs);
|
||||
return basic_json(lhs) != rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5688,7 +5727,7 @@ class basic_json
|
|||
switch (lhs_type)
|
||||
{
|
||||
case value_t::array:
|
||||
return (*lhs.m_value.array) < (*rhs.m_value.array);
|
||||
return *lhs.m_value.array < *rhs.m_value.array;
|
||||
|
||||
case value_t::object:
|
||||
return *lhs.m_value.object < *rhs.m_value.object;
|
||||
|
@ -5754,7 +5793,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator<(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs < basic_json(rhs));
|
||||
return lhs < basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5765,7 +5804,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator<(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) < rhs);
|
||||
return basic_json(lhs) < rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5800,7 +5839,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator<=(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs <= basic_json(rhs));
|
||||
return lhs <= basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5811,7 +5850,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator<=(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) <= rhs);
|
||||
return basic_json(lhs) <= rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5846,7 +5885,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator>(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs > basic_json(rhs));
|
||||
return lhs > basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5857,7 +5896,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator>(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) > rhs);
|
||||
return basic_json(lhs) > rhs;
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5892,7 +5931,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator>=(const_reference lhs, const ScalarType rhs) noexcept
|
||||
{
|
||||
return (lhs >= basic_json(rhs));
|
||||
return lhs >= basic_json(rhs);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -5903,7 +5942,7 @@ class basic_json
|
|||
std::is_scalar<ScalarType>::value, int>::type = 0>
|
||||
friend bool operator>=(const ScalarType lhs, const_reference rhs) noexcept
|
||||
{
|
||||
return (basic_json(lhs) >= rhs);
|
||||
return basic_json(lhs) >= rhs;
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
@ -5949,8 +5988,8 @@ class basic_json
|
|||
friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
|
||||
{
|
||||
// read width member and use it as indentation parameter if nonzero
|
||||
const bool pretty_print = (o.width() > 0);
|
||||
const auto indentation = (pretty_print ? o.width() : 0);
|
||||
const bool pretty_print = o.width() > 0;
|
||||
const auto indentation = pretty_print ? o.width() : 0;
|
||||
|
||||
// reset width to 0 for subsequent calls to this stream
|
||||
o.width(0);
|
||||
|
@ -6006,9 +6045,6 @@ class basic_json
|
|||
@pre The container storage is contiguous. Violating this precondition
|
||||
yields undefined behavior. **This precondition is enforced with an
|
||||
assertion.**
|
||||
@pre Each element of the container has a size of 1 byte. Violating this
|
||||
precondition yields undefined behavior. **This precondition is enforced
|
||||
with a static assertion.**
|
||||
|
||||
@warning There is no way to enforce all preconditions at compile-time. If
|
||||
the function is called with a noncompliant container and with
|
||||
|
@ -6051,6 +6087,7 @@ class basic_json
|
|||
|
||||
@since version 2.0.3 (contiguous containers)
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json parse(detail::input_adapter&& i,
|
||||
const parser_callback_t cb = nullptr,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -6088,9 +6125,6 @@ class basic_json
|
|||
@pre The container storage is contiguous. Violating this precondition
|
||||
yields undefined behavior. **This precondition is enforced with an
|
||||
assertion.**
|
||||
@pre Each element of the container has a size of 1 byte. Violating this
|
||||
precondition yields undefined behavior. **This precondition is enforced
|
||||
with a static assertion.**
|
||||
|
||||
@warning There is no way to enforce all preconditions at compile-time. If
|
||||
the function is called with a noncompliant container and with
|
||||
|
@ -6127,13 +6161,9 @@ class basic_json
|
|||
const bool strict = true)
|
||||
{
|
||||
assert(sax);
|
||||
switch (format)
|
||||
{
|
||||
case input_format_t::json:
|
||||
return parser(std::move(i)).sax_parse(sax, strict);
|
||||
default:
|
||||
return detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
|
||||
}
|
||||
return format == input_format_t::json
|
||||
? parser(std::move(i)).sax_parse(sax, strict)
|
||||
: detail::binary_reader<basic_json, SAX>(std::move(i)).sax_parse(format, sax, strict);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -6826,6 +6856,7 @@ class basic_json
|
|||
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
|
||||
since 3.2.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json from_cbor(detail::input_adapter&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -6841,6 +6872,7 @@ class basic_json
|
|||
*/
|
||||
template<typename A1, typename A2,
|
||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
||||
JSON_NODISCARD
|
||||
static basic_json from_cbor(A1 && a1, A2 && a2,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -6933,6 +6965,7 @@ class basic_json
|
|||
@a strict parameter since 3.0.0; added @a allow_exceptions parameter
|
||||
since 3.2.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json from_msgpack(detail::input_adapter&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -6948,6 +6981,7 @@ class basic_json
|
|||
*/
|
||||
template<typename A1, typename A2,
|
||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
||||
JSON_NODISCARD
|
||||
static basic_json from_msgpack(A1 && a1, A2 && a2,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -7019,6 +7053,7 @@ class basic_json
|
|||
|
||||
@since version 3.1.0; added @a allow_exceptions parameter since 3.2.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json from_ubjson(detail::input_adapter&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -7034,6 +7069,7 @@ class basic_json
|
|||
*/
|
||||
template<typename A1, typename A2,
|
||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
||||
JSON_NODISCARD
|
||||
static basic_json from_ubjson(A1 && a1, A2 && a2,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -7104,6 +7140,7 @@ class basic_json
|
|||
@sa @ref from_ubjson(detail::input_adapter&&, const bool, const bool) for the
|
||||
related UBJSON format
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json from_bson(detail::input_adapter&& i,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -7119,6 +7156,7 @@ class basic_json
|
|||
*/
|
||||
template<typename A1, typename A2,
|
||||
detail::enable_if_t<std::is_constructible<detail::input_adapter, A1, A2>::value, int> = 0>
|
||||
JSON_NODISCARD
|
||||
static basic_json from_bson(A1 && a1, A2 && a2,
|
||||
const bool strict = true,
|
||||
const bool allow_exceptions = true)
|
||||
|
@ -7454,63 +7492,58 @@ class basic_json
|
|||
const auto operation_add = [&result](json_pointer & ptr, basic_json val)
|
||||
{
|
||||
// adding to the root of the target document means replacing it
|
||||
if (ptr.is_root())
|
||||
if (ptr.empty())
|
||||
{
|
||||
result = val;
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
||||
// make sure the top element of the pointer exists
|
||||
json_pointer top_pointer = ptr.top();
|
||||
if (top_pointer != ptr)
|
||||
{
|
||||
// make sure the top element of the pointer exists
|
||||
json_pointer top_pointer = ptr.top();
|
||||
if (top_pointer != ptr)
|
||||
result.at(top_pointer);
|
||||
}
|
||||
|
||||
// get reference to parent of JSON pointer ptr
|
||||
const auto last_path = ptr.pop_back();
|
||||
basic_json& parent = result[ptr];
|
||||
|
||||
switch (parent.m_type)
|
||||
{
|
||||
case value_t::null:
|
||||
case value_t::object:
|
||||
{
|
||||
result.at(top_pointer);
|
||||
// use operator[] to add value
|
||||
parent[last_path] = val;
|
||||
break;
|
||||
}
|
||||
|
||||
// get reference to parent of JSON pointer ptr
|
||||
const auto last_path = ptr.pop_back();
|
||||
basic_json& parent = result[ptr];
|
||||
|
||||
switch (parent.m_type)
|
||||
case value_t::array:
|
||||
{
|
||||
case value_t::null:
|
||||
case value_t::object:
|
||||
if (last_path == "-")
|
||||
{
|
||||
// use operator[] to add value
|
||||
parent[last_path] = val;
|
||||
break;
|
||||
// special case: append to back
|
||||
parent.push_back(val);
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
else
|
||||
{
|
||||
if (last_path == "-")
|
||||
const auto idx = json_pointer::array_index(last_path);
|
||||
if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
|
||||
{
|
||||
// special case: append to back
|
||||
parent.push_back(val);
|
||||
// avoid undefined behavior
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
}
|
||||
else
|
||||
{
|
||||
const auto idx = json_pointer::array_index(last_path);
|
||||
if (JSON_UNLIKELY(static_cast<size_type>(idx) > parent.size()))
|
||||
{
|
||||
// avoid undefined behavior
|
||||
JSON_THROW(out_of_range::create(401, "array index " + std::to_string(idx) + " is out of range"));
|
||||
}
|
||||
|
||||
// default case: insert add offset
|
||||
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
|
||||
}
|
||||
break;
|
||||
// default case: insert add offset
|
||||
parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
|
||||
}
|
||||
|
||||
// LCOV_EXCL_START
|
||||
default:
|
||||
{
|
||||
// if there exists a parent it cannot be primitive
|
||||
assert(false);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
break;
|
||||
}
|
||||
|
||||
// if there exists a parent it cannot be primitive
|
||||
default: // LCOV_EXCL_LINE
|
||||
assert(false); // LCOV_EXCL_LINE
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7665,7 +7698,7 @@ class basic_json
|
|||
break;
|
||||
}
|
||||
|
||||
case patch_operations::invalid:
|
||||
default:
|
||||
{
|
||||
// op must be "add", "remove", "replace", "move", "copy", or
|
||||
// "test"
|
||||
|
@ -7710,6 +7743,7 @@ class basic_json
|
|||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
JSON_NODISCARD
|
||||
static basic_json diff(const basic_json& source, const basic_json& target,
|
||||
const std::string& path = "")
|
||||
{
|
||||
|
@ -7729,106 +7763,105 @@ class basic_json
|
|||
{
|
||||
{"op", "replace"}, {"path", path}, {"value", target}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
else
|
||||
|
||||
switch (source.type())
|
||||
{
|
||||
switch (source.type())
|
||||
case value_t::array:
|
||||
{
|
||||
case value_t::array:
|
||||
// first pass: traverse common elements
|
||||
std::size_t i = 0;
|
||||
while (i < source.size() and i < target.size())
|
||||
{
|
||||
// first pass: traverse common elements
|
||||
std::size_t i = 0;
|
||||
while (i < source.size() and i < target.size())
|
||||
{
|
||||
// recursive call to compare array values at index i
|
||||
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
|
||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||
++i;
|
||||
}
|
||||
|
||||
// i now reached the end of at least one array
|
||||
// in a second pass, traverse the remaining elements
|
||||
|
||||
// remove my remaining elements
|
||||
const auto end_index = static_cast<difference_type>(result.size());
|
||||
while (i < source.size())
|
||||
{
|
||||
// add operations in reverse order to avoid invalid
|
||||
// indices
|
||||
result.insert(result.begin() + end_index, object(
|
||||
{
|
||||
{"op", "remove"},
|
||||
{"path", path + "/" + std::to_string(i)}
|
||||
}));
|
||||
++i;
|
||||
}
|
||||
|
||||
// add other remaining elements
|
||||
while (i < target.size())
|
||||
{
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "add"},
|
||||
{"path", path + "/" + std::to_string(i)},
|
||||
{"value", target[i]}
|
||||
});
|
||||
++i;
|
||||
}
|
||||
|
||||
break;
|
||||
// recursive call to compare array values at index i
|
||||
auto temp_diff = diff(source[i], target[i], path + "/" + std::to_string(i));
|
||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||
++i;
|
||||
}
|
||||
|
||||
case value_t::object:
|
||||
// i now reached the end of at least one array
|
||||
// in a second pass, traverse the remaining elements
|
||||
|
||||
// remove my remaining elements
|
||||
const auto end_index = static_cast<difference_type>(result.size());
|
||||
while (i < source.size())
|
||||
{
|
||||
// first pass: traverse this object's elements
|
||||
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
||||
// add operations in reverse order to avoid invalid
|
||||
// indices
|
||||
result.insert(result.begin() + end_index, object(
|
||||
{
|
||||
// escape the key name to be used in a JSON patch
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
|
||||
if (target.find(it.key()) != target.end())
|
||||
{
|
||||
// recursive call to compare object values at key it
|
||||
auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
|
||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a key that is not in o -> remove it
|
||||
result.push_back(object(
|
||||
{
|
||||
{"op", "remove"}, {"path", path + "/" + key}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// second pass: traverse other object's elements
|
||||
for (auto it = target.cbegin(); it != target.cend(); ++it)
|
||||
{
|
||||
if (source.find(it.key()) == source.end())
|
||||
{
|
||||
// found a key that is not in this -> add it
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "add"}, {"path", path + "/" + key},
|
||||
{"value", it.value()}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
{"op", "remove"},
|
||||
{"path", path + "/" + std::to_string(i)}
|
||||
}));
|
||||
++i;
|
||||
}
|
||||
|
||||
default:
|
||||
// add other remaining elements
|
||||
while (i < target.size())
|
||||
{
|
||||
// both primitive type: replace value
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "replace"}, {"path", path}, {"value", target}
|
||||
{"op", "add"},
|
||||
{"path", path + "/" + std::to_string(i)},
|
||||
{"value", target[i]}
|
||||
});
|
||||
break;
|
||||
++i;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::object:
|
||||
{
|
||||
// first pass: traverse this object's elements
|
||||
for (auto it = source.cbegin(); it != source.cend(); ++it)
|
||||
{
|
||||
// escape the key name to be used in a JSON patch
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
|
||||
if (target.find(it.key()) != target.end())
|
||||
{
|
||||
// recursive call to compare object values at key it
|
||||
auto temp_diff = diff(it.value(), target[it.key()], path + "/" + key);
|
||||
result.insert(result.end(), temp_diff.begin(), temp_diff.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
// found a key that is not in o -> remove it
|
||||
result.push_back(object(
|
||||
{
|
||||
{"op", "remove"}, {"path", path + "/" + key}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// second pass: traverse other object's elements
|
||||
for (auto it = target.cbegin(); it != target.cend(); ++it)
|
||||
{
|
||||
if (source.find(it.key()) == source.end())
|
||||
{
|
||||
// found a key that is not in this -> add it
|
||||
const auto key = json_pointer::escape(it.key());
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "add"}, {"path", path + "/" + key},
|
||||
{"value", it.value()}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// both primitive type: replace value
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "replace"}, {"path", path}, {"value", target}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8012,4 +8045,4 @@ inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std
|
|||
|
||||
#include <nlohmann/detail/macro_unscope.hpp>
|
||||
|
||||
#endif
|
||||
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef NLOHMANN_JSON_FWD_HPP
|
||||
#define NLOHMANN_JSON_FWD_HPP
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
#include <cstdint> // int64_t, uint64_t
|
||||
#include <map> // map
|
||||
|
@ -61,4 +61,4 @@ uses the standard template types.
|
|||
using json = basic_json<>;
|
||||
} // namespace nlohmann
|
||||
|
||||
#endif
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
|
|
@ -12,6 +12,7 @@ nlohmann_json_multiple_headers = declare_dependency(
|
|||
include_directories: include_directories('include')
|
||||
)
|
||||
|
||||
if not meson.is_subproject()
|
||||
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
||||
|
||||
pkgc = import('pkgconfig')
|
||||
|
@ -19,3 +20,4 @@ pkgc.generate(name: 'nlohmann_json',
|
|||
version: meson.project_version(),
|
||||
description: 'JSON for Modern C++'
|
||||
)
|
||||
endif
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -64,7 +64,12 @@ set_target_properties(doctest_main PROPERTIES
|
|||
COMPILE_DEFINITIONS "$<$<CXX_COMPILER_ID:MSVC>:_SCL_SECURE_NO_WARNINGS>"
|
||||
COMPILE_OPTIONS "$<$<CXX_COMPILER_ID:MSVC>:/EHsc;$<$<CONFIG:Release>:/Od>>"
|
||||
)
|
||||
target_compile_features(doctest_main PUBLIC cxx_std_11)
|
||||
|
||||
if (${CMAKE_VERSION} VERSION_LESS "3.8.0")
|
||||
target_compile_features(catch_main PUBLIC cxx_range_for)
|
||||
else()
|
||||
target_compile_features(catch_main PUBLIC cxx_std_11)
|
||||
endif()
|
||||
target_include_directories(doctest_main PRIVATE "thirdparty/doctest")
|
||||
|
||||
# https://stackoverflow.com/questions/2368811/how-to-set-warning-level-in-cmake
|
||||
|
|
|
@ -111,6 +111,12 @@ struct my_allocator : std::allocator<T>
|
|||
p->~T();
|
||||
}
|
||||
}
|
||||
|
||||
template <class U>
|
||||
struct rebind
|
||||
{
|
||||
using other = my_allocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
// allows deletion of raw pointer, usually hold by json_value
|
||||
|
|
|
@ -150,7 +150,7 @@ class alt_string
|
|||
}
|
||||
|
||||
private:
|
||||
std::string str_impl;
|
||||
std::string str_impl {};
|
||||
|
||||
friend bool ::operator<(const char*, const alt_string&);
|
||||
};
|
||||
|
|
|
@ -1968,7 +1968,7 @@ TEST_CASE("all CBOR first bytes")
|
|||
|
||||
try
|
||||
{
|
||||
json::from_cbor(std::vector<uint8_t>(1, byte));
|
||||
auto res = json::from_cbor(std::vector<uint8_t>(1, byte));
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
|
|
|
@ -126,7 +126,7 @@ class SaxEventLogger
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> events;
|
||||
std::vector<std::string> events {};
|
||||
bool errored = false;
|
||||
};
|
||||
|
||||
|
|
|
@ -124,7 +124,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
|
|||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> events;
|
||||
std::vector<std::string> events {};
|
||||
};
|
||||
|
||||
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
||||
|
|
|
@ -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(std::string(json::json_pointer(ptr)) == ptr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,4 +461,137 @@ TEST_CASE("JSON pointers")
|
|||
CHECK(j.is_object());
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("empty, push, pop and parent")
|
||||
{
|
||||
const json j =
|
||||
{
|
||||
{"", "Hello"},
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{
|
||||
"answer", {
|
||||
{"everything", 42}
|
||||
}
|
||||
},
|
||||
{"list", {1, 0, 2}},
|
||||
{
|
||||
"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99},
|
||||
{"", "empty string"},
|
||||
{"/", "slash"},
|
||||
{"~", "tilde"},
|
||||
{"~1", "tilde1"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// empty json_pointer returns the root JSON-object
|
||||
auto ptr = ""_json_pointer;
|
||||
CHECK(ptr.empty());
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
// simple field access
|
||||
ptr.push_back("pi");
|
||||
CHECK(!ptr.empty());
|
||||
CHECK(j[ptr] == j["pi"]);
|
||||
|
||||
ptr.pop_back();
|
||||
CHECK(ptr.empty());
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
// object and children access
|
||||
const std::string answer("answer");
|
||||
ptr.push_back(answer);
|
||||
ptr.push_back("everything");
|
||||
CHECK(!ptr.empty());
|
||||
CHECK(j[ptr] == j["answer"]["everything"]);
|
||||
|
||||
ptr.pop_back();
|
||||
ptr.pop_back();
|
||||
CHECK(ptr.empty());
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
// push key which has to be encoded
|
||||
ptr.push_back("object");
|
||||
ptr.push_back("/");
|
||||
CHECK(j[ptr] == j["object"]["/"]);
|
||||
CHECK(ptr.to_string() == "/object/~1");
|
||||
|
||||
CHECK(j[ptr.parent_pointer()] == j["object"]);
|
||||
ptr = ptr.parent_pointer().parent_pointer();
|
||||
CHECK(ptr.empty());
|
||||
CHECK(j[ptr] == j);
|
||||
// parent-pointer of the empty json_pointer is empty
|
||||
ptr = ptr.parent_pointer();
|
||||
CHECK(ptr.empty());
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
CHECK_THROWS_WITH(ptr.pop_back(),
|
||||
"[json.exception.out_of_range.405] JSON pointer has no parent");
|
||||
}
|
||||
|
||||
SECTION("operators")
|
||||
{
|
||||
const json j =
|
||||
{
|
||||
{"", "Hello"},
|
||||
{"pi", 3.141},
|
||||
{"happy", true},
|
||||
{"name", "Niels"},
|
||||
{"nothing", nullptr},
|
||||
{
|
||||
"answer", {
|
||||
{"everything", 42}
|
||||
}
|
||||
},
|
||||
{"list", {1, 0, 2}},
|
||||
{
|
||||
"object", {
|
||||
{"currency", "USD"},
|
||||
{"value", 42.99},
|
||||
{"", "empty string"},
|
||||
{"/", "slash"},
|
||||
{"~", "tilde"},
|
||||
{"~1", "tilde1"}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// empty json_pointer returns the root JSON-object
|
||||
auto ptr = ""_json_pointer;
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
// simple field access
|
||||
ptr = ptr / "pi";
|
||||
CHECK(j[ptr] == j["pi"]);
|
||||
|
||||
ptr.pop_back();
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
// object and children access
|
||||
const std::string answer("answer");
|
||||
ptr /= answer;
|
||||
ptr = ptr / "everything";
|
||||
CHECK(j[ptr] == j["answer"]["everything"]);
|
||||
|
||||
ptr.pop_back();
|
||||
ptr.pop_back();
|
||||
CHECK(j[ptr] == j);
|
||||
|
||||
CHECK(ptr / ""_json_pointer == ptr);
|
||||
CHECK(j["/answer"_json_pointer / "/everything"_json_pointer] == j["answer"]["everything"]);
|
||||
|
||||
// list children access
|
||||
CHECK(j["/list"_json_pointer / 1] == j["list"][1]);
|
||||
|
||||
// push key which has to be encoded
|
||||
ptr /= "object";
|
||||
ptr = ptr / "/";
|
||||
CHECK(j[ptr] == j["object"]["/"]);
|
||||
CHECK(ptr.to_string() == "/object/~1");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -308,7 +308,7 @@ TEST_CASE("README" * doctest::skip())
|
|||
// }
|
||||
|
||||
// calculate a JSON patch from two JSON values
|
||||
json::diff(j_result, j_original);
|
||||
auto res = json::diff(j_result, j_original);
|
||||
// [
|
||||
// { "op":" replace", "path": "/baz", "value": ["one", "two", "three"] },
|
||||
// { "op":"remove","path":"/hello" },
|
||||
|
|
|
@ -129,8 +129,10 @@ struct nocopy
|
|||
|
||||
struct Data
|
||||
{
|
||||
std::string a;
|
||||
std::string b;
|
||||
Data() = default;
|
||||
Data(const std::string& a_, const std::string b_) : a(a_), b(b_) {}
|
||||
std::string a {};
|
||||
std::string b {};
|
||||
};
|
||||
|
||||
void from_json(const json& j, Data& data)
|
||||
|
@ -1705,13 +1707,81 @@ TEST_CASE("regression tests")
|
|||
|
||||
std::map<std::string, Data> expected
|
||||
{
|
||||
{"1", {"testa_1", "testb_1" }},
|
||||
{"1", {"testa_1", "testb_1"}},
|
||||
{"2", {"testa_2", "testb_2"}},
|
||||
{"3", {"testa_3", "testb_3"}},
|
||||
};
|
||||
const auto data = j.get<decltype(expected)>();
|
||||
CHECK(expected == data);
|
||||
}
|
||||
|
||||
SECTION("issue #1445 - buffer overflow in dumping invalid utf-8 strings")
|
||||
{
|
||||
SECTION("a bunch of -1, ensure_ascii=true")
|
||||
{
|
||||
json dump_test;
|
||||
std::vector<char> data(300, -1);
|
||||
std::vector<std::string> vec_string(300, "\\ufffd");
|
||||
std::string s{data.data(), data.size()};
|
||||
dump_test["1"] = s;
|
||||
std::ostringstream os;
|
||||
os << "{\"1\":\"";
|
||||
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
|
||||
os << "\"}";
|
||||
s = dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
|
||||
CHECK(s == os.str());
|
||||
}
|
||||
SECTION("a bunch of -2, ensure_ascii=false")
|
||||
{
|
||||
json dump_test;
|
||||
std::vector<char> data(500, -2);
|
||||
std::vector<std::string> vec_string(500, "\xEF\xBF\xBD");
|
||||
std::string s{data.data(), data.size()};
|
||||
dump_test["1"] = s;
|
||||
std::ostringstream os;
|
||||
os << "{\"1\":\"";
|
||||
std::copy( vec_string.begin(), vec_string.end(), std::ostream_iterator<std::string>(os));
|
||||
os << "\"}";
|
||||
s = dump_test.dump(-1, ' ', false, nlohmann::json::error_handler_t::replace);
|
||||
CHECK(s == os.str());
|
||||
}
|
||||
SECTION("test case in issue #1445")
|
||||
{
|
||||
nlohmann::json dump_test;
|
||||
const int data[] =
|
||||
{
|
||||
109, 108, 103, 125, -122, -53, 115,
|
||||
18, 3, 0, 102, 19, 1, 15,
|
||||
-110, 13, -3, -1, -81, 32, 2,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
8, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, -80, 2,
|
||||
0, 0, 96, -118, 46, -116, 46,
|
||||
109, -84, -87, 108, 14, 109, -24,
|
||||
-83, 13, -18, -51, -83, -52, -115,
|
||||
14, 6, 32, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
64, 3, 0, 0, 0, 35, -74,
|
||||
-73, 55, 57, -128, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 33, 0, 0, 0, -96,
|
||||
-54, -28, -26
|
||||
};
|
||||
std::string s;
|
||||
for (unsigned i = 0; i < sizeof(data) / sizeof(int); i++)
|
||||
{
|
||||
s += static_cast<char>(data[i]);
|
||||
}
|
||||
dump_test["1"] = s;
|
||||
dump_test.dump(-1, ' ', true, nlohmann::json::error_handler_t::replace);
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("issue #1447 - Integer Overflow (OSS-Fuzz 12506)")
|
||||
{
|
||||
json j = json::parse("[-9223372036854775808]");
|
||||
CHECK(j.dump() == "[-9223372036854775808]");
|
||||
}
|
||||
}
|
||||
|
||||
#if not defined(JSON_NOEXCEPTION)
|
||||
|
|
|
@ -2130,7 +2130,7 @@ TEST_CASE("all UBJSON first bytes")
|
|||
|
||||
try
|
||||
{
|
||||
json::from_ubjson(std::vector<uint8_t>(1, byte));
|
||||
auto res = json::from_ubjson(std::vector<uint8_t>(1, byte));
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
|
|
|
@ -598,9 +598,8 @@ struct pod_serializer
|
|||
static void to_json(BasicJsonType& j, const T& t) noexcept
|
||||
{
|
||||
auto bytes = static_cast< const unsigned char*>(static_cast<const void*>(&t));
|
||||
std::uint64_t value = bytes[0];
|
||||
for (auto i = 1; i < 8; ++i)
|
||||
value |= std::uint64_t{bytes[i]} << 8 * i;
|
||||
std::uint64_t value;
|
||||
std::memcpy(&value, bytes, sizeof(value));
|
||||
nlohmann::to_json(j, value);
|
||||
}
|
||||
};
|
||||
|
|
27
third_party/cpplint/LICENSE
vendored
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