mirror of
https://github.com/nlohmann/json.git
synced 2026-06-21 03:34:17 +00:00
Compare commits
5 Commits
develop
...
clang-format
| Author | SHA1 | Date | |
|---|---|---|---|
| af3f87e84e | |||
| 286f0c7647 | |||
| d16f4496eb | |||
| e87dba5cc3 | |||
| 311ad0b877 |
+23
-10
@@ -1,4 +1,3 @@
|
|||||||
#AccessModifierOffset: 2
|
|
||||||
AlignAfterOpenBracket: Align
|
AlignAfterOpenBracket: Align
|
||||||
AlignConsecutiveAssignments: false
|
AlignConsecutiveAssignments: false
|
||||||
#AlignConsecutiveBitFields: false
|
#AlignConsecutiveBitFields: false
|
||||||
@@ -12,7 +11,7 @@ AllowAllConstructorInitializersOnNextLine: false
|
|||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
AllowShortBlocksOnASingleLine: Empty
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
#AllowShortEnumsOnASingleLine: true
|
AllowShortEnumsOnASingleLine: true
|
||||||
AllowShortFunctionsOnASingleLine: Empty
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
AllowShortIfStatementsOnASingleLine: Never
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
AllowShortLambdasOnASingleLine: Empty
|
AllowShortLambdasOnASingleLine: Empty
|
||||||
@@ -30,27 +29,26 @@ BraceWrapping:
|
|||||||
AfterControlStatement: Always
|
AfterControlStatement: Always
|
||||||
AfterEnum: true
|
AfterEnum: true
|
||||||
AfterFunction: true
|
AfterFunction: true
|
||||||
AfterNamespace: false
|
AfterNamespace: true
|
||||||
AfterStruct: true
|
AfterStruct: true
|
||||||
AfterUnion: true
|
AfterUnion: true
|
||||||
AfterExternBlock: false
|
AfterExternBlock: false
|
||||||
BeforeCatch: true
|
BeforeCatch: true
|
||||||
BeforeElse: true
|
BeforeElse: true
|
||||||
#BeforeLambdaBody: false
|
BeforeLambdaBody: false
|
||||||
#BeforeWhile: false
|
BeforeWhile: false
|
||||||
SplitEmptyFunction: false
|
SplitEmptyFunction: false
|
||||||
SplitEmptyRecord: false
|
SplitEmptyRecord: false
|
||||||
SplitEmptyNamespace: false
|
SplitEmptyNamespace: false
|
||||||
BreakBeforeTernaryOperators: true
|
BreakBeforeTernaryOperators: true
|
||||||
BreakConstructorInitializers: BeforeComma
|
BreakConstructorInitializers: BeforeComma
|
||||||
BreakStringLiterals: false
|
BreakStringLiterals: false
|
||||||
ColumnLimit: 0
|
ColumnLimit: 160
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ConstructorInitializerIndentWidth: 2
|
ConstructorInitializerIndentWidth: 2
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: false
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
FixNamespaceComments: true
|
FixNamespaceComments: true
|
||||||
IncludeBlocks: Preserve
|
|
||||||
#IndentCaseBlocks: false
|
#IndentCaseBlocks: false
|
||||||
IndentCaseLabels: true
|
IndentCaseLabels: true
|
||||||
IndentGotoLabels: false
|
IndentGotoLabels: false
|
||||||
@@ -60,7 +58,6 @@ KeepEmptyLinesAtTheStartOfBlocks: false
|
|||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
NamespaceIndentation: None
|
NamespaceIndentation: None
|
||||||
ReflowComments: false
|
ReflowComments: false
|
||||||
SortIncludes: true
|
|
||||||
SortUsingDeclarations: true
|
SortUsingDeclarations: true
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterLogicalNot: false
|
SpaceAfterLogicalNot: false
|
||||||
@@ -79,6 +76,22 @@ SpacesInConditionalStatement: false
|
|||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: false
|
||||||
SpacesInParentheses: false
|
SpacesInParentheses: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
Standard: c++11
|
Standard: Latest
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
|
||||||
|
# what to do with include blocks
|
||||||
|
SortIncludes: true
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^".*"'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '<[^\/]+>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<(nlohmann)\/-*'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 4
|
||||||
|
|
||||||
|
Macros:
|
||||||
|
- JSON_PRIVATE_UNLESS_TESTED=private
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ To make changes, you need to edit the following files:
|
|||||||
## Note
|
## Note
|
||||||
|
|
||||||
- If you open a pull request, the code will be automatically tested with [Valgrind](http://valgrind.org)'s Memcheck tool to detect memory leaks. Please be aware that the execution with Valgrind _may_ in rare cases yield different behavior than running the code directly. This can result in failing unit tests which run successfully without Valgrind.
|
- If you open a pull request, the code will be automatically tested with [Valgrind](http://valgrind.org)'s Memcheck tool to detect memory leaks. Please be aware that the execution with Valgrind _may_ in rare cases yield different behavior than running the code directly. This can result in failing unit tests which run successfully without Valgrind.
|
||||||
- There is a Makefile target `make pretty` which runs [Artistic Style](http://astyle.sourceforge.net) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
|
- There is a Makefile target `make pretty` which runs [Clang-Format](https://clang.llvm.org/docs/ClangFormat.html) to fix indentation. If possible, run it before opening the pull request. Otherwise, we shall run it afterward.
|
||||||
|
|
||||||
## Please don't
|
## Please don't
|
||||||
|
|
||||||
|
|||||||
@@ -21,15 +21,9 @@ jobs:
|
|||||||
|
|
||||||
check:
|
check:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
container: silkeh/clang:dev
|
||||||
env:
|
env:
|
||||||
MAIN_DIR: ${{ github.workspace }}/main
|
MAIN_DIR: ${{ github.workspace }}/main
|
||||||
INCLUDE_DIR: ${{ github.workspace }}/main/single_include/nlohmann
|
|
||||||
TOOL_DIR: ${{ github.workspace }}/tools/tools/amalgamate
|
|
||||||
ASTYLE_FLAGS: >
|
|
||||||
--style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block
|
|
||||||
--indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type
|
|
||||||
--align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date
|
|
||||||
--formatted
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout pull request
|
- name: Checkout pull request
|
||||||
@@ -44,27 +38,7 @@ jobs:
|
|||||||
path: tools
|
path: tools
|
||||||
ref: develop
|
ref: develop
|
||||||
|
|
||||||
- name: Install astyle
|
|
||||||
run: |
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install astyle
|
|
||||||
|
|
||||||
- name: Check amalgamation
|
- name: Check amalgamation
|
||||||
run: |
|
run: |
|
||||||
cd $MAIN_DIR
|
cd $MAIN_DIR
|
||||||
|
make check-amalgamation
|
||||||
rm -fr $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json_fwd.hpp~
|
|
||||||
cp $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json.hpp~
|
|
||||||
cp $INCLUDE_DIR/json_fwd.hpp $INCLUDE_DIR/json_fwd.hpp~
|
|
||||||
|
|
||||||
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
|
|
||||||
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
|
|
||||||
echo "Format (1)"
|
|
||||||
astyle $ASTYLE_FLAGS --suffix=none --quiet $INCLUDE_DIR/json.hpp $INCLUDE_DIR/json_fwd.hpp
|
|
||||||
|
|
||||||
diff $INCLUDE_DIR/json.hpp~ $INCLUDE_DIR/json.hpp
|
|
||||||
diff $INCLUDE_DIR/json_fwd.hpp~ $INCLUDE_DIR/json_fwd.hpp
|
|
||||||
|
|
||||||
astyle $ASTYLE_FLAGS $(find docs/examples include tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name '*.cu' \) -not -path 'tests/thirdparty/*' -not -path 'tests/abi/include/nlohmann/*' | sort)
|
|
||||||
echo Check
|
|
||||||
find $MAIN_DIR -name '*.orig' -exec false {} \+
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ jobs:
|
|||||||
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
container: ghcr.io/nlohmann/json-ci:v2.4.0
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
target: [ci_cppcheck, ci_test_valgrind, ci_test_amalgamation, ci_test_single_header, ci_single_binaries, ci_infer]
|
target: [ci_cppcheck, ci_test_valgrind, ci_test_single_header, ci_single_binaries, ci_infer]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Run CMake
|
- name: Run CMake
|
||||||
@@ -54,6 +54,18 @@ jobs:
|
|||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --target ${{ matrix.target }}
|
run: cmake --build build --target ${{ matrix.target }}
|
||||||
|
|
||||||
|
ci_test_amalgamation:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container: silkeh/clang:dev
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Get latest CMake and ninja
|
||||||
|
uses: lukka/get-cmake@v3.27.7
|
||||||
|
- name: Run CMake
|
||||||
|
run: cmake -S . -B build -DJSON_CI=On
|
||||||
|
- name: Build
|
||||||
|
run: cmake --build build --target ci_test_amalgamation
|
||||||
|
|
||||||
ci_static_analysis_ubuntu:
|
ci_static_analysis_ubuntu:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
|
|||||||
@@ -142,33 +142,9 @@ pvs_studio:
|
|||||||
# Code format and source amalgamation
|
# Code format and source amalgamation
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
# call the Artistic Style pretty printer on all source files
|
|
||||||
pretty:
|
|
||||||
astyle \
|
|
||||||
--style=allman \
|
|
||||||
--indent=spaces=4 \
|
|
||||||
--indent-modifiers \
|
|
||||||
--indent-switches \
|
|
||||||
--indent-preproc-block \
|
|
||||||
--indent-preproc-define \
|
|
||||||
--indent-col1-comments \
|
|
||||||
--pad-oper \
|
|
||||||
--pad-header \
|
|
||||||
--align-pointer=type \
|
|
||||||
--align-reference=type \
|
|
||||||
--add-braces \
|
|
||||||
--squeeze-lines=2 \
|
|
||||||
--convert-tabs \
|
|
||||||
--close-templates \
|
|
||||||
--lineend=linux \
|
|
||||||
--preserve-date \
|
|
||||||
--suffix=none \
|
|
||||||
--formatted \
|
|
||||||
$(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/examples/*.cpp
|
|
||||||
|
|
||||||
# call the Clang-Format on all source files
|
# call the Clang-Format on all source files
|
||||||
pretty_format:
|
pretty:
|
||||||
for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
|
clang-format --Werror --verbose -i $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
|
||||||
|
|
||||||
# create single header files and pretty print
|
# create single header files and pretty print
|
||||||
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
|
amalgamate: $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE)
|
||||||
|
|||||||
@@ -1774,8 +1774,8 @@ The library itself consists of a single header file licensed under the MIT licen
|
|||||||
- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file
|
- [**amalgamate.py - Amalgamate C source and header files**](https://github.com/edlund/amalgamate) to create a single header file
|
||||||
- [**American fuzzy lop**](https://lcamtuf.coredump.cx/afl/) for fuzz testing
|
- [**American fuzzy lop**](https://lcamtuf.coredump.cx/afl/) for fuzz testing
|
||||||
- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
|
- [**AppVeyor**](https://www.appveyor.com) for [continuous integration](https://ci.appveyor.com/project/nlohmann/json) on Windows
|
||||||
- [**Artistic Style**](http://astyle.sourceforge.net) for automatic source code indentation
|
|
||||||
- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers
|
- [**Clang**](https://clang.llvm.org) for compilation with code sanitizers
|
||||||
|
- [**Clang-Format**](https://clang.llvm.org/docs/ClangFormat.html) for automatic source code indentation
|
||||||
- [**CMake**](https://cmake.org) for build automation
|
- [**CMake**](https://cmake.org) for build automation
|
||||||
- [**Codacy**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json)
|
- [**Codacy**](https://www.codacy.com) for further [code analysis](https://www.codacy.com/app/nlohmann/json)
|
||||||
- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
|
- [**Coveralls**](https://coveralls.io) to measure [code coverage](https://coveralls.io/github/nlohmann/json)
|
||||||
|
|||||||
+6
-31
@@ -8,16 +8,16 @@ set(N 10)
|
|||||||
include(FindPython3)
|
include(FindPython3)
|
||||||
find_package(Python3 COMPONENTS Interpreter)
|
find_package(Python3 COMPONENTS Interpreter)
|
||||||
|
|
||||||
find_program(ASTYLE_TOOL NAMES astyle)
|
|
||||||
execute_process(COMMAND ${ASTYLE_TOOL} --version OUTPUT_VARIABLE ASTYLE_TOOL_VERSION ERROR_VARIABLE ASTYLE_TOOL_VERSION)
|
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" ASTYLE_TOOL_VERSION "${ASTYLE_TOOL_VERSION}")
|
|
||||||
message(STATUS "🔖 Artistic Style ${ASTYLE_TOOL_VERSION} (${ASTYLE_TOOL})")
|
|
||||||
|
|
||||||
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
|
find_program(CLANG_TOOL NAMES clang++-HEAD clang++ clang++-17 clang++-16 clang++-15 clang++-14 clang++-13 clang++-12 clang++-11 clang++)
|
||||||
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
|
execute_process(COMMAND ${CLANG_TOOL} --version OUTPUT_VARIABLE CLANG_TOOL_VERSION ERROR_VARIABLE CLANG_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TOOL_VERSION "${CLANG_TOOL_VERSION}")
|
||||||
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
message(STATUS "🔖 Clang ${CLANG_TOOL_VERSION} (${CLANG_TOOL})")
|
||||||
|
|
||||||
|
find_program(CLANG_FORMAT_TOOL NAMES clang-format)
|
||||||
|
execute_process(COMMAND ${CLANG_FORMAT_TOOL} --version OUTPUT_VARIABLE CLANG_FORMAT_TOOL_VERSION ERROR_VARIABLE CLANG_FORMAT_TOOL_VERSION)
|
||||||
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_FORMAT_TOOL_VERSION "${CLANG_FORMAT_TOOL_VERSION}")
|
||||||
|
message(STATUS "🔖 Clang-Format ${CLANG_FORMAT_TOOL_VERSION} (${CLANG_FORMAT_TOOL})")
|
||||||
|
|
||||||
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
|
find_program(CLANG_TIDY_TOOL NAMES clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14 clang-tidy-13 clang-tidy-12 clang-tidy-11 clang-tidy)
|
||||||
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
|
execute_process(COMMAND ${CLANG_TIDY_TOOL} --version OUTPUT_VARIABLE CLANG_TIDY_TOOL_VERSION ERROR_VARIABLE CLANG_TIDY_TOOL_VERSION)
|
||||||
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
|
string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CLANG_TIDY_TOOL_VERSION "${CLANG_TIDY_TOOL_VERSION}")
|
||||||
@@ -581,33 +581,8 @@ add_custom_target(ci_test_clang_sanitizer
|
|||||||
# Check if header is amalgamated and sources are properly indented.
|
# Check if header is amalgamated and sources are properly indented.
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
set(ASTYLE_FLAGS --style=allman --indent=spaces=4 --indent-modifiers --indent-switches --indent-preproc-block --indent-preproc-define --indent-col1-comments --pad-oper --pad-header --align-pointer=type --align-reference=type --add-brackets --convert-tabs --close-templates --lineend=linux --preserve-date --formatted)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE INDENT_FILES
|
|
||||||
${PROJECT_SOURCE_DIR}/include/nlohmann/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/src/*.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/tests/benchmarks/src/benchmarks.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/docs/examples/*.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
|
||||||
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
|
||||||
add_custom_target(ci_test_amalgamation
|
add_custom_target(ci_test_amalgamation
|
||||||
COMMAND rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~
|
COMMAND make check-amalgamation
|
||||||
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
|
||||||
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
|
||||||
|
|
||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json.json -s .
|
|
||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
|
||||||
COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} --suffix=none --quiet ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
|
||||||
|
|
||||||
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
|
||||||
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
|
||||||
|
|
||||||
COMMAND ${ASTYLE_TOOL} ${ASTYLE_FLAGS} ${INDENT_FILES}
|
|
||||||
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
|
||||||
|
|
||||||
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
|
||||||
COMMENT "Check amalgamation and indentation"
|
COMMENT "Check amalgamation and indentation"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,9 +24,8 @@ struct adl_serializer
|
|||||||
/// @brief convert a JSON value to any value type
|
/// @brief convert a JSON value to any value type
|
||||||
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
|
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
|
||||||
template<typename BasicJsonType, typename TargetType = ValueType>
|
template<typename BasicJsonType, typename TargetType = ValueType>
|
||||||
static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
|
static auto from_json(BasicJsonType&& j, TargetType& val) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
|
||||||
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
|
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
|
||||||
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
|
|
||||||
{
|
{
|
||||||
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
|
::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
|
||||||
}
|
}
|
||||||
@@ -34,19 +33,17 @@ struct adl_serializer
|
|||||||
/// @brief convert a JSON value to any value type
|
/// @brief convert a JSON value to any value type
|
||||||
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
|
/// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
|
||||||
template<typename BasicJsonType, typename TargetType = ValueType>
|
template<typename BasicJsonType, typename TargetType = ValueType>
|
||||||
static auto from_json(BasicJsonType && j) noexcept(
|
static auto from_json(BasicJsonType&& j) noexcept(noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{})))
|
||||||
noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
|
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{}))
|
||||||
-> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
|
|
||||||
{
|
{
|
||||||
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
|
return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief convert any value type to a JSON value
|
/// @brief convert any value type to a JSON value
|
||||||
/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
|
/// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
|
||||||
template<typename BasicJsonType, typename TargetType = ValueType>
|
template<typename BasicJsonType, typename TargetType = ValueType>
|
||||||
static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
|
static auto to_json(BasicJsonType& j, TargetType&& val) noexcept(noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
|
||||||
noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
|
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
|
||||||
-> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
|
|
||||||
{
|
{
|
||||||
::nlohmann::to_json(j, std::forward<TargetType>(val));
|
::nlohmann::to_json(j, std::forward<TargetType>(val));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint8_t, uint64_t
|
#include <cstdint> // uint8_t, uint64_t
|
||||||
#include <tuple> // tie
|
#include <tuple> // tie
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
@@ -27,31 +27,31 @@ class byte_container_with_subtype : public BinaryType
|
|||||||
|
|
||||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||||
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
||||||
: container_type()
|
: container_type()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||||
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
|
byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
|
||||||
: container_type(b)
|
: container_type(b)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||||
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
|
byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||||
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
|
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
|
||||||
: container_type(b)
|
: container_type(b)
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
|
||||||
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
|
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool operator==(const byte_container_with_subtype& rhs) const
|
bool operator==(const byte_container_with_subtype& rhs) const
|
||||||
|
|||||||
@@ -47,54 +47,40 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Construct the namespace ABI tags component
|
// Construct the namespace ABI tags component
|
||||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b
|
||||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
|
||||||
|
|
||||||
#define NLOHMANN_JSON_ABI_TAGS \
|
#define NLOHMANN_JSON_ABI_TAGS NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
|
||||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
|
||||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
|
||||||
|
|
||||||
// Construct the namespace version component
|
// Construct the namespace version component
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch
|
||||||
_v ## major ## _ ## minor ## _ ## patch
|
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
|
||||||
|
|
||||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||||
#else
|
#else
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH)
|
||||||
NLOHMANN_JSON_VERSION_MINOR, \
|
|
||||||
NLOHMANN_JSON_VERSION_PATCH)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Combine namespace components
|
// Combine namespace components
|
||||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b
|
||||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||||
#define NLOHMANN_JSON_NAMESPACE \
|
#define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
|
||||||
NLOHMANN_JSON_ABI_TAGS, \
|
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||||
namespace nlohmann \
|
namespace nlohmann \
|
||||||
{ \
|
{ \
|
||||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||||
NLOHMANN_JSON_ABI_TAGS, \
|
{
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // transform
|
#include <algorithm> // transform
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <forward_list> // forward_list
|
#include <forward_list> // forward_list
|
||||||
#include <iterator> // inserter, front_inserter, end
|
#include <iterator> // inserter, front_inserter, end
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <tuple> // tuple, make_tuple
|
#include <tuple> // tuple, make_tuple
|
||||||
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
|
#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
|
||||||
#include <unordered_map> // unordered_map
|
#include <unordered_map> // unordered_map
|
||||||
#include <utility> // pair, declval
|
#include <utility> // pair, declval
|
||||||
#include <valarray> // valarray
|
#include <valarray> // valarray
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -44,10 +44,9 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// overloads for basic_json template parameters
|
// overloads for basic_json template parameters
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
typename ArithmeticType,
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
enable_if_t<std::is_arithmetic<ArithmeticType>::value && !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value, int> = 0>
|
||||||
int > = 0 >
|
|
||||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
switch (static_cast<value_t>(j))
|
switch (static_cast<value_t>(j))
|
||||||
@@ -100,13 +99,12 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t&
|
|||||||
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template<typename BasicJsonType,
|
||||||
typename BasicJsonType, typename StringType,
|
typename StringType,
|
||||||
enable_if_t <
|
enable_if_t<std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value &&
|
||||||
std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
|
is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value &&
|
||||||
&& is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
|
!std::is_same<typename BasicJsonType::string_t, StringType>::value && !is_json_ref<StringType>::value,
|
||||||
&& !std::is_same<typename BasicJsonType::string_t, StringType>::value
|
int> = 0>
|
||||||
&& !is_json_ref<StringType>::value, int > = 0 >
|
|
||||||
inline void from_json(const BasicJsonType& j, StringType& s)
|
inline void from_json(const BasicJsonType& j, StringType& s)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
|
||||||
@@ -136,8 +134,7 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_int
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !JSON_DISABLE_ENUM_SERIALIZATION
|
#if !JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
template<typename BasicJsonType, typename EnumType,
|
template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
||||||
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
|
||||||
inline void from_json(const BasicJsonType& j, EnumType& e)
|
inline void from_json(const BasicJsonType& j, EnumType& e)
|
||||||
{
|
{
|
||||||
typename std::underlying_type<EnumType>::type val;
|
typename std::underlying_type<EnumType>::type val;
|
||||||
@@ -147,8 +144,7 @@ inline void from_json(const BasicJsonType& j, EnumType& e)
|
|||||||
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
#endif // JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
|
|
||||||
// forward_list doesn't have an insert method
|
// forward_list doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T, typename Allocator,
|
template<typename BasicJsonType, typename T, typename Allocator, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
|
||||||
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -156,16 +152,13 @@ inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l
|
|||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
l.clear();
|
l.clear();
|
||||||
std::transform(j.rbegin(), j.rend(),
|
std::transform(j.rbegin(), j.rend(), std::front_inserter(l), [](const BasicJsonType& i) {
|
||||||
std::front_inserter(l), [](const BasicJsonType & i)
|
|
||||||
{
|
|
||||||
return i.template get<T>();
|
return i.template get<T>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// valarray doesn't have an insert method
|
// valarray doesn't have an insert method
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T, enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
||||||
enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
|
|
||||||
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -173,16 +166,14 @@ inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
|
|||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
l.resize(j.size());
|
l.resize(j.size());
|
||||||
std::transform(j.begin(), j.end(), std::begin(l),
|
std::transform(j.begin(), j.end(), std::begin(l), [](const BasicJsonType& elem) {
|
||||||
[](const BasicJsonType & elem)
|
|
||||||
{
|
|
||||||
return elem.template get<T>();
|
return elem.template get<T>();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
-> decltype(j.template get<T>(), void())
|
-> decltype(j.template get<T>(), void())
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
@@ -197,9 +188,7 @@ inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N>
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr, priority_tag<2> /*unused*/) -> decltype(j.template get<T>(), void())
|
||||||
priority_tag<2> /*unused*/)
|
|
||||||
-> decltype(j.template get<T>(), void())
|
|
||||||
{
|
{
|
||||||
for (std::size_t i = 0; i < N; ++i)
|
for (std::size_t i = 0; i < N; ++i)
|
||||||
{
|
{
|
||||||
@@ -207,23 +196,17 @@ auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t<
|
typename ConstructibleArrayType,
|
||||||
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
|
enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
|
||||||
int> = 0>
|
|
||||||
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
|
auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
|
||||||
-> decltype(
|
-> decltype(arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()), j.template get<typename ConstructibleArrayType::value_type>(), void())
|
||||||
arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
|
|
||||||
j.template get<typename ConstructibleArrayType::value_type>(),
|
|
||||||
void())
|
|
||||||
{
|
{
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
ConstructibleArrayType ret;
|
ConstructibleArrayType ret;
|
||||||
ret.reserve(j.size());
|
ret.reserve(j.size());
|
||||||
std::transform(j.begin(), j.end(),
|
std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
|
||||||
std::inserter(ret, end(ret)), [](const BasicJsonType & i)
|
|
||||||
{
|
|
||||||
// get<BasicJsonType>() returns *this, this won't call a from_json
|
// get<BasicJsonType>() returns *this, this won't call a from_json
|
||||||
// method when value_type is BasicJsonType
|
// method when value_type is BasicJsonType
|
||||||
return i.template get<typename ConstructibleArrayType::value_type>();
|
return i.template get<typename ConstructibleArrayType::value_type>();
|
||||||
@@ -231,20 +214,15 @@ auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, p
|
|||||||
arr = std::move(ret);
|
arr = std::move(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t<
|
typename ConstructibleArrayType,
|
||||||
std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
|
enable_if_t<std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value, int> = 0>
|
||||||
int> = 0>
|
inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<0> /*unused*/)
|
||||||
inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
|
|
||||||
priority_tag<0> /*unused*/)
|
|
||||||
{
|
{
|
||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
ConstructibleArrayType ret;
|
ConstructibleArrayType ret;
|
||||||
std::transform(
|
std::transform(j.begin(), j.end(), std::inserter(ret, end(ret)), [](const BasicJsonType& i) {
|
||||||
j.begin(), j.end(), std::inserter(ret, end(ret)),
|
|
||||||
[](const BasicJsonType & i)
|
|
||||||
{
|
|
||||||
// get<BasicJsonType>() returns *this, this won't call a from_json
|
// get<BasicJsonType>() returns *this, this won't call a from_json
|
||||||
// method when value_type is BasicJsonType
|
// method when value_type is BasicJsonType
|
||||||
return i.template get<typename ConstructibleArrayType::value_type>();
|
return i.template get<typename ConstructibleArrayType::value_type>();
|
||||||
@@ -252,44 +230,41 @@ inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType&
|
|||||||
arr = std::move(ret);
|
arr = std::move(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename ConstructibleArrayType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t <
|
typename ConstructibleArrayType,
|
||||||
is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
|
enable_if_t<is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value &&
|
||||||
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value &&
|
||||||
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value &&
|
||||||
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
|
!std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value && !is_basic_json<ConstructibleArrayType>::value,
|
||||||
!is_basic_json<ConstructibleArrayType>::value,
|
int> = 0>
|
||||||
int > = 0 >
|
|
||||||
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
|
||||||
-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
|
-> decltype(from_json_array_impl(j, arr, priority_tag<3>{}), j.template get<typename ConstructibleArrayType::value_type>(), void())
|
||||||
j.template get<typename ConstructibleArrayType::value_type>(),
|
|
||||||
void())
|
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
from_json_array_impl(j, arr, priority_tag<3> {});
|
from_json_array_impl(j, arr, priority_tag<3>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename T, std::size_t... Idx >
|
template<typename BasicJsonType, typename T, std::size_t... Idx>
|
||||||
std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
|
std::array<T, sizeof...(Idx)>
|
||||||
identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
|
from_json_inplace_array_impl(BasicJsonType&& j, identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
|
||||||
{
|
{
|
||||||
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
|
return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename T, std::size_t N >
|
template<typename BasicJsonType, typename T, std::size_t N>
|
||||||
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
|
auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
|
||||||
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
|
-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{}))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
|
return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
@@ -303,7 +278,8 @@ inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t&
|
|||||||
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
template<typename BasicJsonType,
|
||||||
|
typename ConstructibleObjectType,
|
||||||
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
|
||||||
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
||||||
{
|
{
|
||||||
@@ -315,11 +291,7 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
ConstructibleObjectType ret;
|
ConstructibleObjectType ret;
|
||||||
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
|
||||||
using value_type = typename ConstructibleObjectType::value_type;
|
using value_type = typename ConstructibleObjectType::value_type;
|
||||||
std::transform(
|
std::transform(inner_object->begin(), inner_object->end(), std::inserter(ret, ret.begin()), [](typename BasicJsonType::object_t::value_type const& p) {
|
||||||
inner_object->begin(), inner_object->end(),
|
|
||||||
std::inserter(ret, ret.begin()),
|
|
||||||
[](typename BasicJsonType::object_t::value_type const & p)
|
|
||||||
{
|
|
||||||
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
|
return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
|
||||||
});
|
});
|
||||||
obj = std::move(ret);
|
obj = std::move(ret);
|
||||||
@@ -329,14 +301,13 @@ inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
|
|||||||
// (BooleanType, etc..); note: Is it really necessary to provide explicit
|
// (BooleanType, etc..); note: Is it really necessary to provide explicit
|
||||||
// overloads for boolean_t etc. in case of a custom BooleanType which is not
|
// overloads for boolean_t etc. in case of a custom BooleanType which is not
|
||||||
// an arithmetic type?
|
// an arithmetic type?
|
||||||
template < typename BasicJsonType, typename ArithmeticType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t <
|
typename ArithmeticType,
|
||||||
std::is_arithmetic<ArithmeticType>::value&&
|
enable_if_t<std::is_arithmetic<ArithmeticType>::value && !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value &&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
|
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value &&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
|
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value &&
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
|
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
int> = 0>
|
||||||
int > = 0 >
|
|
||||||
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
inline void from_json(const BasicJsonType& j, ArithmeticType& val)
|
||||||
{
|
{
|
||||||
switch (static_cast<value_t>(j))
|
switch (static_cast<value_t>(j))
|
||||||
@@ -379,46 +350,48 @@ std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<
|
|||||||
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
|
return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, class A1, class A2 >
|
template<typename BasicJsonType, class A1, class A2>
|
||||||
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
|
std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
|
||||||
{
|
{
|
||||||
return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
|
return { std::forward<BasicJsonType>(j).at(0).template get<A1>(), std::forward<BasicJsonType>(j).at(1).template get<A2>() };
|
||||||
std::forward<BasicJsonType>(j).at(1).template get<A2>()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename A1, typename A2>
|
template<typename BasicJsonType, typename A1, typename A2>
|
||||||
inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
|
inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
|
||||||
{
|
{
|
||||||
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
|
p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>>{}, priority_tag<0>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
|
||||||
{
|
{
|
||||||
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
|
return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename... Args>
|
template<typename BasicJsonType, typename... Args>
|
||||||
inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
|
inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
|
||||||
{
|
{
|
||||||
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
|
t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename TupleRelated>
|
template<typename BasicJsonType, typename TupleRelated>
|
||||||
auto from_json(BasicJsonType&& j, TupleRelated&& t)
|
auto from_json(BasicJsonType&& j, TupleRelated&& t)
|
||||||
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
|
-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{}))
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
|
||||||
}
|
}
|
||||||
|
|
||||||
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
|
return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
|
template<typename BasicJsonType,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename Key,
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename Value,
|
||||||
|
typename Compare,
|
||||||
|
typename Allocator,
|
||||||
|
typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
|
||||||
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -436,9 +409,13 @@ inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
|
template<typename BasicJsonType,
|
||||||
typename = enable_if_t < !std::is_constructible <
|
typename Key,
|
||||||
typename BasicJsonType::string_t, Key >::value >>
|
typename Value,
|
||||||
|
typename Hash,
|
||||||
|
typename KeyEqual,
|
||||||
|
typename Allocator,
|
||||||
|
typename = enable_if_t<!std::is_constructible<typename BasicJsonType::string_t, Key>::value>>
|
||||||
inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
|
||||||
@@ -471,9 +448,8 @@ inline void from_json(const BasicJsonType& j, std_fs::path& p)
|
|||||||
struct from_json_fn
|
struct from_json_fn
|
||||||
{
|
{
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
auto operator()(const BasicJsonType& j, T&& val) const
|
auto operator()(const BasicJsonType& j, T&& val) const noexcept(noexcept(from_json(j, std::forward<T>(val))))
|
||||||
noexcept(noexcept(from_json(j, std::forward<T>(val))))
|
-> decltype(from_json(j, std::forward<T>(val)))
|
||||||
-> decltype(from_json(j, std::forward<T>(val)))
|
|
||||||
{
|
{
|
||||||
return from_json(j, std::forward<T>(val));
|
return from_json(j, std::forward<T>(val));
|
||||||
}
|
}
|
||||||
@@ -485,10 +461,10 @@ struct from_json_fn
|
|||||||
/// namespace to hold default `from_json` function
|
/// namespace to hold default `from_json` function
|
||||||
/// to see why this is required:
|
/// to see why this is required:
|
||||||
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
||||||
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
|
JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
|
||||||
detail::static_const<detail::from_json_fn>::value;
|
detail::static_const<detail::from_json_fn>::value;
|
||||||
#ifndef JSON_HAS_CPP_17
|
#ifndef JSON_HAS_CPP_17
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -9,12 +9,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cmath> // signbit, isfinite
|
#include <cmath> // signbit, isfinite
|
||||||
#include <cstdint> // intN_t, uintN_t
|
#include <cstdint> // intN_t, uintN_t
|
||||||
#include <cstring> // memcpy, memmove
|
#include <cstring> // memcpy, memmove
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <type_traits> // conditional
|
#include <type_traits> // conditional
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
@@ -54,14 +54,17 @@ Target reinterpret_bits(const Source source)
|
|||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct diyfp // f * 2^e
|
struct diyfp // f * 2^e
|
||||||
{
|
{
|
||||||
static constexpr int kPrecision = 64; // = q
|
static constexpr int kPrecision = 64; // = q
|
||||||
|
|
||||||
std::uint64_t f = 0;
|
std::uint64_t f = 0;
|
||||||
int e = 0;
|
int e = 0;
|
||||||
|
|
||||||
constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
|
constexpr diyfp(std::uint64_t f_, int e_) noexcept
|
||||||
|
: f(f_)
|
||||||
|
, e(e_)
|
||||||
|
{}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief returns x - y
|
@brief returns x - y
|
||||||
@@ -72,7 +75,7 @@ struct diyfp // f * 2^e
|
|||||||
JSON_ASSERT(x.e == y.e);
|
JSON_ASSERT(x.e == y.e);
|
||||||
JSON_ASSERT(x.f >= y.f);
|
JSON_ASSERT(x.f >= y.f);
|
||||||
|
|
||||||
return {x.f - y.f, x.e};
|
return { x.f - y.f, x.e };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -133,11 +136,11 @@ struct diyfp // f * 2^e
|
|||||||
// Effectively we only need to add the highest bit in p_lo to p_hi (and
|
// Effectively we only need to add the highest bit in p_lo to p_hi (and
|
||||||
// Q_hi + 1 does not overflow).
|
// Q_hi + 1 does not overflow).
|
||||||
|
|
||||||
Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
|
Q += std::uint64_t{ 1 } << (64u - 32u - 1u); // round, ties up
|
||||||
|
|
||||||
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
|
const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
|
||||||
|
|
||||||
return {h, x.e + y.e + 64};
|
return { h, x.e + y.e + 64 };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -168,7 +171,7 @@ struct diyfp // f * 2^e
|
|||||||
JSON_ASSERT(delta >= 0);
|
JSON_ASSERT(delta >= 0);
|
||||||
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
|
JSON_ASSERT(((x.f << delta) >> delta) == x.f);
|
||||||
|
|
||||||
return {x.f << delta, target_exponent};
|
return { x.f << delta, target_exponent };
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,24 +201,21 @@ boundaries compute_boundaries(FloatType value)
|
|||||||
// If v is normalized:
|
// If v is normalized:
|
||||||
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
|
// value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
|
||||||
|
|
||||||
static_assert(std::numeric_limits<FloatType>::is_iec559,
|
static_assert(std::numeric_limits<FloatType>::is_iec559, "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
|
||||||
"internal error: dtoa_short requires an IEEE-754 floating-point implementation");
|
|
||||||
|
|
||||||
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
|
constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
|
||||||
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
|
constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
|
||||||
constexpr int kMinExp = 1 - kBias;
|
constexpr int kMinExp = 1 - kBias;
|
||||||
constexpr std::uint64_t kHiddenBit = std::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, std::uint32_t, std::uint64_t >::type;
|
using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t>::type;
|
||||||
|
|
||||||
const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
|
const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
|
||||||
const std::uint64_t E = bits >> (kPrecision - 1);
|
const std::uint64_t E = bits >> (kPrecision - 1);
|
||||||
const std::uint64_t F = bits & (kHiddenBit - 1);
|
const std::uint64_t F = bits & (kHiddenBit - 1);
|
||||||
|
|
||||||
const bool is_denormal = E == 0;
|
const bool is_denormal = E == 0;
|
||||||
const diyfp v = is_denormal
|
const diyfp v = is_denormal ? diyfp(F, kMinExp) : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
|
||||||
? diyfp(F, kMinExp)
|
|
||||||
: diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
|
|
||||||
|
|
||||||
// Compute the boundaries m- and m+ of the floating-point value
|
// Compute the boundaries m- and m+ of the floating-point value
|
||||||
// v = f * 2^e.
|
// v = f * 2^e.
|
||||||
@@ -240,9 +240,8 @@ boundaries compute_boundaries(FloatType value)
|
|||||||
|
|
||||||
const bool lower_boundary_is_closer = F == 0 && E > 1;
|
const bool lower_boundary_is_closer = F == 0 && E > 1;
|
||||||
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
|
||||||
const diyfp m_minus = lower_boundary_is_closer
|
const diyfp m_minus = lower_boundary_is_closer ? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
||||||
? diyfp(4 * v.f - 1, v.e - 2) // (B)
|
: diyfp(2 * v.f - 1, v.e - 1); // (A)
|
||||||
: diyfp(2 * v.f - 1, v.e - 1); // (A)
|
|
||||||
|
|
||||||
// Determine the normalized w+ = m+.
|
// Determine the normalized w+ = m+.
|
||||||
const diyfp w_plus = diyfp::normalize(m_plus);
|
const diyfp w_plus = diyfp::normalize(m_plus);
|
||||||
@@ -250,7 +249,7 @@ boundaries compute_boundaries(FloatType value)
|
|||||||
// Determine w- = m- such that e_(w-) = e_(w+).
|
// Determine w- = m- such that e_(w-) = e_(w+).
|
||||||
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
|
const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
|
||||||
|
|
||||||
return {diyfp::normalize(v), w_minus, w_plus};
|
return { diyfp::normalize(v), w_minus, w_plus };
|
||||||
}
|
}
|
||||||
|
|
||||||
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
|
// Given normalized diyfp w, Grisu needs to find a (normalized) cached
|
||||||
@@ -311,7 +310,7 @@ boundaries compute_boundaries(FloatType value)
|
|||||||
constexpr int kAlpha = -60;
|
constexpr int kAlpha = -60;
|
||||||
constexpr int kGamma = -32;
|
constexpr int kGamma = -32;
|
||||||
|
|
||||||
struct cached_power // c = f * 2^e ~= 10^k
|
struct cached_power // c = f * 2^e ~= 10^k
|
||||||
{
|
{
|
||||||
std::uint64_t f;
|
std::uint64_t f;
|
||||||
int e;
|
int e;
|
||||||
@@ -380,97 +379,35 @@ inline cached_power get_cached_power_for_binary_exponent(int e)
|
|||||||
constexpr int kCachedPowersMinDecExp = -300;
|
constexpr int kCachedPowersMinDecExp = -300;
|
||||||
constexpr int kCachedPowersDecStep = 8;
|
constexpr int kCachedPowersDecStep = 8;
|
||||||
|
|
||||||
static constexpr std::array<cached_power, 79> 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 },
|
||||||
{ 0xAB70FE17C79AC6CA, -1060, -300 },
|
{ 0x823C12795DB6CE57, -847, -236 }, { 0xC21094364DFB5637, -821, -228 }, { 0x9096EA6F3848984F, -794, -220 }, { 0xD77485CB25823AC7, -768, -212 },
|
||||||
{ 0xFF77B1FCBEBCDC4F, -1034, -292 },
|
{ 0xA086CFCD97BF97F4, -741, -204 }, { 0xEF340A98172AACE5, -715, -196 }, { 0xB23867FB2A35B28E, -688, -188 }, { 0x84C8D4DFD2C63F3B, -661, -180 },
|
||||||
{ 0xBE5691EF416BD60C, -1007, -284 },
|
{ 0xC5DD44271AD3CDBA, -635, -172 }, { 0x936B9FCEBB25C996, -608, -164 }, { 0xDBAC6C247D62A584, -582, -156 }, { 0xA3AB66580D5FDAF6, -555, -148 },
|
||||||
{ 0x8DD01FAD907FFC3C, -980, -276 },
|
{ 0xF3E2F893DEC3F126, -529, -140 }, { 0xB5B5ADA8AAFF80B8, -502, -132 }, { 0x87625F056C7C4A8B, -475, -124 }, { 0xC9BCFF6034C13053, -449, -116 },
|
||||||
{ 0xD3515C2831559A83, -954, -268 },
|
{ 0x964E858C91BA2655, -422, -108 }, { 0xDFF9772470297EBD, -396, -100 }, { 0xA6DFBD9FB8E5B88F, -369, -92 }, { 0xF8A95FCF88747D94, -343, -84 },
|
||||||
{ 0x9D71AC8FADA6C9B5, -927, -260 },
|
{ 0xB94470938FA89BCF, -316, -76 }, { 0x8A08F0F8BF0F156B, -289, -68 }, { 0xCDB02555653131B6, -263, -60 }, { 0x993FE2C6D07B7FAC, -236, -52 },
|
||||||
{ 0xEA9C227723EE8BCB, -901, -252 },
|
{ 0xE45C10C42A2B3B06, -210, -44 }, { 0xAA242499697392D3, -183, -36 }, { 0xFD87B5F28300CA0E, -157, -28 }, { 0xBCE5086492111AEB, -130, -20 },
|
||||||
{ 0xAECC49914078536D, -874, -244 },
|
{ 0x8CBCCC096F5088CC, -103, -12 }, { 0xD1B71758E219652C, -77, -4 }, { 0x9C40000000000000, -50, 4 }, { 0xE8D4A51000000000, -24, 12 },
|
||||||
{ 0x823C12795DB6CE57, -847, -236 },
|
{ 0xAD78EBC5AC620000, 3, 20 }, { 0x813F3978F8940984, 30, 28 }, { 0xC097CE7BC90715B3, 56, 36 }, { 0x8F7E32CE7BEA5C70, 83, 44 },
|
||||||
{ 0xC21094364DFB5637, -821, -228 },
|
{ 0xD5D238A4ABE98068, 109, 52 }, { 0x9F4F2726179A2245, 136, 60 }, { 0xED63A231D4C4FB27, 162, 68 }, { 0xB0DE65388CC8ADA8, 189, 76 },
|
||||||
{ 0x9096EA6F3848984F, -794, -220 },
|
{ 0x83C7088E1AAB65DB, 216, 84 }, { 0xC45D1DF942711D9A, 242, 92 }, { 0x924D692CA61BE758, 269, 100 }, { 0xDA01EE641A708DEA, 295, 108 },
|
||||||
{ 0xD77485CB25823AC7, -768, -212 },
|
{ 0xA26DA3999AEF774A, 322, 116 }, { 0xF209787BB47D6B85, 348, 124 }, { 0xB454E4A179DD1877, 375, 132 }, { 0x865B86925B9BC5C2, 402, 140 },
|
||||||
{ 0xA086CFCD97BF97F4, -741, -204 },
|
{ 0xC83553C5C8965D3D, 428, 148 }, { 0x952AB45CFA97A0B3, 455, 156 }, { 0xDE469FBD99A05FE3, 481, 164 }, { 0xA59BC234DB398C25, 508, 172 },
|
||||||
{ 0xEF340A98172AACE5, -715, -196 },
|
{ 0xF6C69A72A3989F5C, 534, 180 }, { 0xB7DCBF5354E9BECE, 561, 188 }, { 0x88FCF317F22241E2, 588, 196 }, { 0xCC20CE9BD35C78A5, 614, 204 },
|
||||||
{ 0xB23867FB2A35B28E, -688, -188 },
|
{ 0x98165AF37B2153DF, 641, 212 }, { 0xE2A0B5DC971F303A, 667, 220 }, { 0xA8D9D1535CE3B396, 694, 228 }, { 0xFB9B7CD9A4A7443C, 720, 236 },
|
||||||
{ 0x84C8D4DFD2C63F3B, -661, -180 },
|
{ 0xBB764C4CA7A44410, 747, 244 }, { 0x8BAB8EEFB6409C1A, 774, 252 }, { 0xD01FEF10A657842C, 800, 260 }, { 0x9B10A4E5E9913129, 827, 268 },
|
||||||
{ 0xC5DD44271AD3CDBA, -635, -172 },
|
{ 0xE7109BFBA19C0C9D, 853, 276 }, { 0xAC2820D9623BF429, 880, 284 }, { 0x80444B5E7AA7CF85, 907, 292 }, { 0xBF21E44003ACDD2D, 933, 300 },
|
||||||
{ 0x936B9FCEBB25C996, -608, -164 },
|
{ 0x8E679C2F5E44FF8F, 960, 308 }, { 0xD433179D9C8CB841, 986, 316 }, { 0x9E19DB92B4E31BA9, 1013, 324 },
|
||||||
{ 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
|
// This computation gives exactly the same results for k as
|
||||||
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
|
// k = ceil((kAlpha - e - 1) * 0.30102999566398114)
|
||||||
// for |e| <= 1500, but doesn't require floating-point operations.
|
// for |e| <= 1500, but doesn't require floating-point operations.
|
||||||
// NB: log_10(2) ~= 78913 / 2^18
|
// NB: log_10(2) ~= 78913 / 2^18
|
||||||
JSON_ASSERT(e >= -1500);
|
JSON_ASSERT(e >= -1500);
|
||||||
JSON_ASSERT(e <= 1500);
|
JSON_ASSERT(e <= 1500);
|
||||||
const int f = kAlpha - e - 1;
|
const int f = kAlpha - e - 1;
|
||||||
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
|
const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
|
||||||
|
|
||||||
@@ -501,50 +438,49 @@ inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
|
|||||||
if (n >= 100000000)
|
if (n >= 100000000)
|
||||||
{
|
{
|
||||||
pow10 = 100000000;
|
pow10 = 100000000;
|
||||||
return 9;
|
return 9;
|
||||||
}
|
}
|
||||||
if (n >= 10000000)
|
if (n >= 10000000)
|
||||||
{
|
{
|
||||||
pow10 = 10000000;
|
pow10 = 10000000;
|
||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
if (n >= 1000000)
|
if (n >= 1000000)
|
||||||
{
|
{
|
||||||
pow10 = 1000000;
|
pow10 = 1000000;
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
if (n >= 100000)
|
if (n >= 100000)
|
||||||
{
|
{
|
||||||
pow10 = 100000;
|
pow10 = 100000;
|
||||||
return 6;
|
return 6;
|
||||||
}
|
}
|
||||||
if (n >= 10000)
|
if (n >= 10000)
|
||||||
{
|
{
|
||||||
pow10 = 10000;
|
pow10 = 10000;
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
if (n >= 1000)
|
if (n >= 1000)
|
||||||
{
|
{
|
||||||
pow10 = 1000;
|
pow10 = 1000;
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
if (n >= 100)
|
if (n >= 100)
|
||||||
{
|
{
|
||||||
pow10 = 100;
|
pow10 = 100;
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
if (n >= 10)
|
if (n >= 10)
|
||||||
{
|
{
|
||||||
pow10 = 10;
|
pow10 = 10;
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pow10 = 1;
|
pow10 = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
|
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)
|
||||||
std::uint64_t rest, std::uint64_t ten_k)
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(len >= 1);
|
JSON_ASSERT(len >= 1);
|
||||||
JSON_ASSERT(dist <= delta);
|
JSON_ASSERT(dist <= delta);
|
||||||
@@ -570,9 +506,7 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
|
|||||||
// The tests are written in this order to avoid overflow in unsigned
|
// The tests are written in this order to avoid overflow in unsigned
|
||||||
// integer arithmetic.
|
// integer arithmetic.
|
||||||
|
|
||||||
while (rest < dist
|
while (rest < dist && delta - rest >= ten_k && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
|
||||||
&& delta - rest >= ten_k
|
|
||||||
&& (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(buf[len - 1] != '0');
|
JSON_ASSERT(buf[len - 1] != '0');
|
||||||
buf[len - 1]--;
|
buf[len - 1]--;
|
||||||
@@ -584,8 +518,7 @@ inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t d
|
|||||||
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
|
Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
|
||||||
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
|
M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
|
||||||
*/
|
*/
|
||||||
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
|
||||||
diyfp M_minus, diyfp w, diyfp M_plus)
|
|
||||||
{
|
{
|
||||||
static_assert(kAlpha >= -60, "internal error");
|
static_assert(kAlpha >= -60, "internal error");
|
||||||
static_assert(kGamma <= -32, "internal error");
|
static_assert(kGamma <= -32, "internal error");
|
||||||
@@ -605,8 +538,8 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
JSON_ASSERT(M_plus.e >= kAlpha);
|
JSON_ASSERT(M_plus.e >= kAlpha);
|
||||||
JSON_ASSERT(M_plus.e <= kGamma);
|
JSON_ASSERT(M_plus.e <= kGamma);
|
||||||
|
|
||||||
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
|
||||||
std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
|
std::uint64_t dist = diyfp::sub(M_plus, w).f; // (significand of (M+ - w ), implicit exponent is e)
|
||||||
|
|
||||||
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
|
// Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
|
||||||
//
|
//
|
||||||
@@ -615,10 +548,10 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
// = ((p1 ) * 2^-e + (p2 )) * 2^e
|
// = ((p1 ) * 2^-e + (p2 )) * 2^e
|
||||||
// = p1 + p2 * 2^e
|
// = p1 + p2 * 2^e
|
||||||
|
|
||||||
const diyfp one(std::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<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
|
auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
|
||||||
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
|
||||||
|
|
||||||
// 1)
|
// 1)
|
||||||
//
|
//
|
||||||
@@ -661,7 +594,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
// = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
|
||||||
//
|
//
|
||||||
JSON_ASSERT(d <= 9);
|
JSON_ASSERT(d <= 9);
|
||||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
|
// M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
|
||||||
//
|
//
|
||||||
@@ -680,7 +613,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
// Note:
|
// Note:
|
||||||
// Since rest and delta share the same exponent e, it suffices to
|
// Since rest and delta share the same exponent e, it suffices to
|
||||||
// compare the significands.
|
// compare the significands.
|
||||||
const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
|
const std::uint64_t rest = (std::uint64_t{ p1 } << -one.e) + p2;
|
||||||
if (rest <= delta)
|
if (rest <= delta)
|
||||||
{
|
{
|
||||||
// V = buffer * 10^n, with M- <= V <= M+.
|
// V = buffer * 10^n, with M- <= V <= M+.
|
||||||
@@ -696,7 +629,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
//
|
//
|
||||||
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
|
// 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
|
||||||
//
|
//
|
||||||
const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
|
const std::uint64_t ten_n = std::uint64_t{ pow10 } << -one.e;
|
||||||
grisu2_round(buffer, length, dist, delta, rest, ten_n);
|
grisu2_round(buffer, length, dist, delta, rest, ten_n);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -760,15 +693,15 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
//
|
//
|
||||||
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
|
||||||
p2 *= 10;
|
p2 *= 10;
|
||||||
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
|
||||||
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
|
// M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
|
||||||
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
// = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
|
||||||
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
// = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||||
//
|
//
|
||||||
JSON_ASSERT(d <= 9);
|
JSON_ASSERT(d <= 9);
|
||||||
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
|
||||||
//
|
//
|
||||||
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
// M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
|
||||||
//
|
//
|
||||||
@@ -784,7 +717,7 @@ inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
|
|||||||
// p2 * 2^e <= 10^m * delta * 2^e
|
// p2 * 2^e <= 10^m * delta * 2^e
|
||||||
// p2 <= 10^m * delta
|
// p2 <= 10^m * delta
|
||||||
delta *= 10;
|
delta *= 10;
|
||||||
dist *= 10;
|
dist *= 10;
|
||||||
if (p2 <= delta)
|
if (p2 <= delta)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
@@ -825,8 +758,7 @@ len is the length of the buffer (number of decimal digits)
|
|||||||
The buffer must be large enough, i.e. >= max_digits10.
|
The buffer must be large enough, i.e. >= max_digits10.
|
||||||
*/
|
*/
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
JSON_HEDLEY_NON_NULL(1)
|
||||||
inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
inline void grisu2(char* buf, int& len, int& decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
|
||||||
diyfp m_minus, diyfp v, diyfp m_plus)
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(m_plus.e == m_minus.e);
|
JSON_ASSERT(m_plus.e == m_minus.e);
|
||||||
JSON_ASSERT(m_plus.e == v.e);
|
JSON_ASSERT(m_plus.e == v.e);
|
||||||
@@ -842,12 +774,12 @@ inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
|||||||
|
|
||||||
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
|
const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
|
||||||
|
|
||||||
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
|
const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
|
||||||
|
|
||||||
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
|
// The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
|
||||||
const diyfp w = diyfp::mul(v, c_minus_k);
|
const diyfp w = diyfp::mul(v, c_minus_k);
|
||||||
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
|
const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
|
||||||
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
|
const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
|
||||||
|
|
||||||
// ----(---+---)---------------(---+---)---------------(---+---)----
|
// ----(---+---)---------------(---+---)---------------(---+---)----
|
||||||
// w- w w+
|
// w- w w+
|
||||||
@@ -871,9 +803,9 @@ inline void grisu2(char* buf, int& len, int& decimal_exponent,
|
|||||||
// Note that this does not mean that Grisu2 always generates the shortest
|
// Note that this does not mean that Grisu2 always generates the shortest
|
||||||
// possible number in the interval (m-, m+).
|
// possible number in the interval (m-, m+).
|
||||||
const diyfp M_minus(w_minus.f + 1, w_minus.e);
|
const diyfp M_minus(w_minus.f + 1, w_minus.e);
|
||||||
const diyfp M_plus (w_plus.f - 1, w_plus.e );
|
const diyfp M_plus(w_plus.f - 1, w_plus.e);
|
||||||
|
|
||||||
decimal_exponent = -cached.k; // = -(-k) = k
|
decimal_exponent = -cached.k; // = -(-k) = k
|
||||||
|
|
||||||
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
|
grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
|
||||||
}
|
}
|
||||||
@@ -887,8 +819,7 @@ template<typename FloatType>
|
|||||||
JSON_HEDLEY_NON_NULL(1)
|
JSON_HEDLEY_NON_NULL(1)
|
||||||
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
|
void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
|
||||||
{
|
{
|
||||||
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
|
static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3, "internal error: not enough precision");
|
||||||
"internal error: not enough precision");
|
|
||||||
|
|
||||||
JSON_ASSERT(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
JSON_ASSERT(value > 0);
|
JSON_ASSERT(value > 0);
|
||||||
@@ -909,7 +840,7 @@ void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
|
|||||||
// NB: If the neighbors are computed for single-precision numbers, there is a single float
|
// NB: If the neighbors are computed for single-precision numbers, there is a single float
|
||||||
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
|
// (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
|
||||||
// value is off by 1 ulp.
|
// value is off by 1 ulp.
|
||||||
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
|
#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
|
||||||
const boundaries w = compute_boundaries(static_cast<double>(value));
|
const boundaries w = compute_boundaries(static_cast<double>(value));
|
||||||
#else
|
#else
|
||||||
const boundaries w = compute_boundaries(value);
|
const boundaries w = compute_boundaries(value);
|
||||||
@@ -928,7 +859,7 @@ JSON_HEDLEY_RETURNS_NON_NULL
|
|||||||
inline char* append_exponent(char* buf, int e)
|
inline char* append_exponent(char* buf, int e)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(e > -1000);
|
JSON_ASSERT(e > -1000);
|
||||||
JSON_ASSERT(e < 1000);
|
JSON_ASSERT(e < 1000);
|
||||||
|
|
||||||
if (e < 0)
|
if (e < 0)
|
||||||
{
|
{
|
||||||
@@ -977,8 +908,7 @@ notation. Otherwise it will be printed in exponential notation.
|
|||||||
*/
|
*/
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
JSON_HEDLEY_NON_NULL(1)
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL
|
||||||
inline char* format_buffer(char* buf, int len, int decimal_exponent,
|
inline char* format_buffer(char* buf, int len, int decimal_exponent, int min_exp, int max_exp)
|
||||||
int min_exp, int max_exp)
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(min_exp < 0);
|
JSON_ASSERT(min_exp < 0);
|
||||||
JSON_ASSERT(max_exp > 0);
|
JSON_ASSERT(max_exp > 0);
|
||||||
@@ -1061,10 +991,9 @@ format. Returns an iterator pointing past-the-end of the decimal representation.
|
|||||||
*/
|
*/
|
||||||
template<typename FloatType>
|
template<typename FloatType>
|
||||||
JSON_HEDLEY_NON_NULL(1, 2)
|
JSON_HEDLEY_NON_NULL(1, 2)
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL char* to_chars(char* first, const char* last, FloatType value)
|
||||||
char* to_chars(char* first, const char* last, FloatType value)
|
|
||||||
{
|
{
|
||||||
static_cast<void>(last); // maybe unused - fix warning
|
static_cast<void>(last); // maybe unused - fix warning
|
||||||
JSON_ASSERT(std::isfinite(value));
|
JSON_ASSERT(std::isfinite(value));
|
||||||
|
|
||||||
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
// Use signbit(value) instead of (value < 0) since signbit works for -0.
|
||||||
@@ -1075,10 +1004,10 @@ char* to_chars(char* first, const char* last, FloatType value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||||
#endif
|
#endif
|
||||||
if (value == 0) // +-0
|
if (value == 0) // +-0
|
||||||
{
|
{
|
||||||
*first++ = '0';
|
*first++ = '0';
|
||||||
// Make it look like a floating-point number (#362, #378)
|
// Make it look like a floating-point number (#362, #378)
|
||||||
@@ -1087,7 +1016,7 @@ char* to_chars(char* first, const char* last, FloatType value)
|
|||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // copy
|
#include <algorithm> // copy
|
||||||
#include <iterator> // begin, end
|
#include <iterator> // begin, end
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <tuple> // tuple, get
|
#include <tuple> // tuple, get
|
||||||
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
|
#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
|
||||||
#include <utility> // move, forward, declval, pair
|
#include <utility> // move, forward, declval, pair
|
||||||
#include <valarray> // valarray
|
#include <valarray> // valarray
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
#include <nlohmann/detail/iterators/iteration_proxy.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -39,7 +39,8 @@ namespace detail
|
|||||||
* https://github.com/nlohmann/json/issues/2865 for more information.
|
* https://github.com/nlohmann/json/issues/2865 for more information.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
template<value_t> struct external_constructor;
|
template<value_t>
|
||||||
|
struct external_constructor;
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct external_constructor<value_t::boolean>
|
struct external_constructor<value_t::boolean>
|
||||||
@@ -75,9 +76,9 @@ struct external_constructor<value_t::string>
|
|||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleStringType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
|
typename CompatibleStringType,
|
||||||
int > = 0 >
|
enable_if_t<!std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
static void construct(BasicJsonType& j, const CompatibleStringType& str)
|
||||||
{
|
{
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
@@ -171,9 +172,9 @@ struct external_constructor<value_t::array>
|
|||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
|
typename CompatibleArrayType,
|
||||||
int > = 0 >
|
enable_if_t<!std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
|
static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||||
{
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
@@ -201,8 +202,7 @@ struct external_constructor<value_t::array>
|
|||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
||||||
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
|
||||||
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
static void construct(BasicJsonType& j, const std::valarray<T>& arr)
|
||||||
{
|
{
|
||||||
j.m_data.m_value.destroy(j.m_data.m_type);
|
j.m_data.m_value.destroy(j.m_data.m_type);
|
||||||
@@ -241,8 +241,9 @@ struct external_constructor<value_t::object>
|
|||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
|
typename CompatibleObjectType,
|
||||||
|
enable_if_t<!std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int> = 0>
|
||||||
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
|
static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||||
{
|
{
|
||||||
using std::begin;
|
using std::begin;
|
||||||
@@ -260,27 +261,27 @@ struct external_constructor<value_t::object>
|
|||||||
// to_json //
|
// to_json //
|
||||||
/////////////
|
/////////////
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
||||||
enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
|
|
||||||
inline void to_json(BasicJsonType& j, T b) noexcept
|
inline void to_json(BasicJsonType& j, T b) noexcept
|
||||||
{
|
{
|
||||||
external_constructor<value_t::boolean>::construct(j, b);
|
external_constructor<value_t::boolean>::construct(j, b);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename BoolRef,
|
template<typename BasicJsonType,
|
||||||
enable_if_t <
|
typename BoolRef,
|
||||||
((std::is_same<std::vector<bool>::reference, BoolRef>::value
|
enable_if_t<((std::is_same<std::vector<bool>::reference, BoolRef>::value &&
|
||||||
&& !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
|
!std::is_same<std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value) ||
|
||||||
|| (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
|
(std::is_same<std::vector<bool>::const_reference, BoolRef>::value &&
|
||||||
&& !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
|
!std::is_same<detail::uncvref_t<std::vector<bool>::const_reference>, typename BasicJsonType::boolean_t>::value)) &&
|
||||||
typename BasicJsonType::boolean_t >::value))
|
std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value,
|
||||||
&& std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
|
int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
|
inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
|
||||||
{
|
{
|
||||||
external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
|
external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleString,
|
template<typename BasicJsonType,
|
||||||
|
typename CompatibleString,
|
||||||
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
|
enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, const CompatibleString& s)
|
inline void to_json(BasicJsonType& j, const CompatibleString& s)
|
||||||
{
|
{
|
||||||
@@ -293,21 +294,22 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
|||||||
external_constructor<value_t::string>::construct(j, std::move(s));
|
external_constructor<value_t::string>::construct(j, std::move(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename FloatType,
|
template<typename BasicJsonType, typename FloatType, enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
|
||||||
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
|
|
||||||
inline void to_json(BasicJsonType& j, FloatType val) noexcept
|
inline void to_json(BasicJsonType& j, FloatType val) noexcept
|
||||||
{
|
{
|
||||||
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
|
external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
|
template<typename BasicJsonType,
|
||||||
|
typename CompatibleNumberUnsignedType,
|
||||||
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
|
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
|
inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
|
||||||
{
|
{
|
||||||
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
|
external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleNumberIntegerType,
|
template<typename BasicJsonType,
|
||||||
|
typename CompatibleNumberIntegerType,
|
||||||
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
|
enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
|
inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
|
||||||
{
|
{
|
||||||
@@ -315,8 +317,7 @@ inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !JSON_DISABLE_ENUM_SERIALIZATION
|
#if !JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
template<typename BasicJsonType, typename EnumType,
|
template<typename BasicJsonType, typename EnumType, enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
||||||
enable_if_t<std::is_enum<EnumType>::value, int> = 0>
|
|
||||||
inline void to_json(BasicJsonType& j, EnumType e) noexcept
|
inline void to_json(BasicJsonType& j, EnumType e) noexcept
|
||||||
{
|
{
|
||||||
using underlying_type = typename std::underlying_type<EnumType>::type;
|
using underlying_type = typename std::underlying_type<EnumType>::type;
|
||||||
@@ -330,14 +331,13 @@ inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
|
|||||||
external_constructor<value_t::array>::construct(j, e);
|
external_constructor<value_t::array>::construct(j, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleArrayType,
|
template<
|
||||||
enable_if_t < is_compatible_array_type<BasicJsonType,
|
typename BasicJsonType,
|
||||||
CompatibleArrayType>::value&&
|
typename CompatibleArrayType,
|
||||||
!is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
|
enable_if_t<is_compatible_array_type<BasicJsonType, CompatibleArrayType>::value && !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value &&
|
||||||
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
|
!is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value &&
|
||||||
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
|
!std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value && !is_basic_json<CompatibleArrayType>::value,
|
||||||
!is_basic_json<CompatibleArrayType>::value,
|
int> = 0>
|
||||||
int > = 0 >
|
|
||||||
inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::array>::construct(j, arr);
|
external_constructor<value_t::array>::construct(j, arr);
|
||||||
@@ -349,8 +349,7 @@ inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bi
|
|||||||
external_constructor<value_t::binary>::construct(j, bin);
|
external_constructor<value_t::binary>::construct(j, bin);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T, enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
||||||
enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
|
|
||||||
inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
|
inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::array>::construct(j, std::move(arr));
|
external_constructor<value_t::array>::construct(j, std::move(arr));
|
||||||
@@ -362,8 +361,9 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
|||||||
external_constructor<value_t::array>::construct(j, std::move(arr));
|
external_constructor<value_t::array>::construct(j, std::move(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename CompatibleObjectType,
|
template<typename BasicJsonType,
|
||||||
enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
|
typename CompatibleObjectType,
|
||||||
|
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value && !is_basic_json<CompatibleObjectType>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::object>::construct(j, obj);
|
external_constructor<value_t::object>::construct(j, obj);
|
||||||
@@ -375,28 +375,31 @@ inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
|||||||
external_constructor<value_t::object>::construct(j, std::move(obj));
|
external_constructor<value_t::object>::construct(j, std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template<typename BasicJsonType,
|
||||||
typename BasicJsonType, typename T, std::size_t N,
|
typename T,
|
||||||
enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
|
std::size_t N,
|
||||||
const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
enable_if_t<!std::is_constructible<typename BasicJsonType::string_t,
|
||||||
int > = 0 >
|
const T (&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
int> = 0>
|
||||||
|
inline void to_json(BasicJsonType& j, const T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::array>::construct(j, arr);
|
external_constructor<value_t::array>::construct(j, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
|
template<typename BasicJsonType,
|
||||||
|
typename T1,
|
||||||
|
typename T2,
|
||||||
|
enable_if_t<std::is_constructible<BasicJsonType, T1>::value && std::is_constructible<BasicJsonType, T2>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
|
inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
|
||||||
{
|
{
|
||||||
j = { p.first, p.second };
|
j = { p.first, p.second };
|
||||||
}
|
}
|
||||||
|
|
||||||
// for https://github.com/nlohmann/json/pull/1134
|
// for https://github.com/nlohmann/json/pull/1134
|
||||||
template<typename BasicJsonType, typename T,
|
template<typename BasicJsonType, typename T, enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
|
||||||
enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
|
|
||||||
inline void to_json(BasicJsonType& j, const T& b)
|
inline void to_json(BasicJsonType& j, const T& b)
|
||||||
{
|
{
|
||||||
j = { {b.key(), b.value()} };
|
j = { { b.key(), b.value() } };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
|
template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
|
||||||
@@ -405,10 +408,10 @@ inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<
|
|||||||
j = { std::get<Idx>(t)... };
|
j = { std::get<Idx>(t)... };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
|
template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int> = 0>
|
||||||
inline void to_json(BasicJsonType& j, const T& t)
|
inline void to_json(BasicJsonType& j, const T& t)
|
||||||
{
|
{
|
||||||
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
|
to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value>{});
|
||||||
}
|
}
|
||||||
|
|
||||||
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||||
@@ -422,8 +425,7 @@ inline void to_json(BasicJsonType& j, const std_fs::path& p)
|
|||||||
struct to_json_fn
|
struct to_json_fn
|
||||||
{
|
{
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
|
auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val)))) -> decltype(to_json(j, std::forward<T>(val)), void())
|
||||||
-> decltype(to_json(j, std::forward<T>(val)), void())
|
|
||||||
{
|
{
|
||||||
return to_json(j, std::forward<T>(val));
|
return to_json(j, std::forward<T>(val));
|
||||||
}
|
}
|
||||||
@@ -434,10 +436,10 @@ struct to_json_fn
|
|||||||
/// namespace to hold default `to_json` function
|
/// namespace to hold default `to_json` function
|
||||||
/// to see why this is required:
|
/// to see why this is required:
|
||||||
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
|
||||||
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
|
||||||
{
|
{
|
||||||
#endif
|
#endif
|
||||||
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
|
JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
|
||||||
detail::static_const<detail::to_json_fn>::value;
|
detail::static_const<detail::to_json_fn>::value;
|
||||||
#ifndef JSON_HAS_CPP_17
|
#ifndef JSON_HAS_CPP_17
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -8,22 +8,22 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // nullptr_t
|
#include <cstddef> // nullptr_t
|
||||||
#include <exception> // exception
|
#include <exception> // exception
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#endif
|
#endif
|
||||||
#include <stdexcept> // runtime_error
|
#include <stdexcept> // runtime_error
|
||||||
#include <string> // to_string
|
#include <string> // to_string
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
|
||||||
#include <nlohmann/detail/string_escape.hpp>
|
|
||||||
#include <nlohmann/detail/input/position_t.hpp>
|
#include <nlohmann/detail/input/position_t.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
#include <nlohmann/detail/string_concat.hpp>
|
#include <nlohmann/detail/string_concat.hpp>
|
||||||
|
#include <nlohmann/detail/string_escape.hpp>
|
||||||
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
@@ -45,11 +45,14 @@ class exception : public std::exception
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// the id of the exception
|
/// the id of the exception
|
||||||
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
|
const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
|
exception(int id_, const char* what_arg)
|
||||||
|
: id(id_)
|
||||||
|
, m(what_arg) // NOLINT(bugprone-throw-keyword-missing)
|
||||||
|
{}
|
||||||
|
|
||||||
static std::string name(const std::string& ename, int id_)
|
static std::string name(const std::string& ename, int id_)
|
||||||
{
|
{
|
||||||
@@ -96,16 +99,16 @@ class exception : public std::exception
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::null: // LCOV_EXCL_LINE
|
case value_t::null: // LCOV_EXCL_LINE
|
||||||
case value_t::string: // LCOV_EXCL_LINE
|
case value_t::string: // LCOV_EXCL_LINE
|
||||||
case value_t::boolean: // LCOV_EXCL_LINE
|
case value_t::boolean: // LCOV_EXCL_LINE
|
||||||
case value_t::number_integer: // LCOV_EXCL_LINE
|
case value_t::number_integer: // LCOV_EXCL_LINE
|
||||||
case value_t::number_unsigned: // LCOV_EXCL_LINE
|
case value_t::number_unsigned: // LCOV_EXCL_LINE
|
||||||
case value_t::number_float: // LCOV_EXCL_LINE
|
case value_t::number_float: // LCOV_EXCL_LINE
|
||||||
case value_t::binary: // LCOV_EXCL_LINE
|
case value_t::binary: // LCOV_EXCL_LINE
|
||||||
case value_t::discarded: // LCOV_EXCL_LINE
|
case value_t::discarded: // LCOV_EXCL_LINE
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
break; // LCOV_EXCL_LINE
|
break; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,9 +117,7 @@ class exception : public std::exception
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
|
auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{}, [](const std::string& a, const std::string& b) {
|
||||||
[](const std::string & a, const std::string & b)
|
|
||||||
{
|
|
||||||
return concat(a, '/', detail::escape(b));
|
return concat(a, '/', detail::escape(b));
|
||||||
});
|
});
|
||||||
return concat('(', str, ") ");
|
return concat('(', str, ") ");
|
||||||
@@ -148,18 +149,20 @@ class parse_error : public exception
|
|||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||||
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
|
static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("parse_error", id_), "parse error",
|
const std::string w = concat(exception::name("parse_error", id_), "parse error", position_string(pos), ": ", exception::diagnostics(context), what_arg);
|
||||||
position_string(pos), ": ", exception::diagnostics(context), what_arg);
|
return { id_, pos.chars_read_total, w.c_str() };
|
||||||
return {id_, pos.chars_read_total, w.c_str()};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||||
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
|
static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("parse_error", id_), "parse error",
|
const std::string w = concat(exception::name("parse_error", id_),
|
||||||
|
"parse error",
|
||||||
(byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
|
(byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
|
||||||
": ", exception::diagnostics(context), what_arg);
|
": ",
|
||||||
return {id_, byte_, w.c_str()};
|
exception::diagnostics(context),
|
||||||
|
what_arg);
|
||||||
|
return { id_, byte_, w.c_str() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -175,12 +178,13 @@ class parse_error : public exception
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
parse_error(int id_, std::size_t byte_, const char* what_arg)
|
parse_error(int id_, std::size_t byte_, const char* what_arg)
|
||||||
: exception(id_, what_arg), byte(byte_) {}
|
: exception(id_, what_arg)
|
||||||
|
, byte(byte_)
|
||||||
|
{}
|
||||||
|
|
||||||
static std::string position_string(const position_t& pos)
|
static std::string position_string(const position_t& pos)
|
||||||
{
|
{
|
||||||
return concat(" at line ", std::to_string(pos.lines_read + 1),
|
return concat(" at line ", std::to_string(pos.lines_read + 1), ", column ", std::to_string(pos.chars_read_current_line));
|
||||||
", column ", std::to_string(pos.chars_read_current_line));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -193,13 +197,14 @@ class invalid_iterator : public exception
|
|||||||
static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
|
static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
|
const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
|
||||||
return {id_, w.c_str()};
|
return { id_, w.c_str() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
invalid_iterator(int id_, const char* what_arg)
|
invalid_iterator(int id_, const char* what_arg)
|
||||||
: exception(id_, what_arg) {}
|
: exception(id_, what_arg)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief exception indicating executing a member function with a wrong type
|
/// @brief exception indicating executing a member function with a wrong type
|
||||||
@@ -211,12 +216,14 @@ class type_error : public exception
|
|||||||
static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
|
static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
|
const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
|
||||||
return {id_, w.c_str()};
|
return { id_, w.c_str() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
type_error(int id_, const char* what_arg)
|
||||||
|
: exception(id_, what_arg)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief exception indicating access out of the defined range
|
/// @brief exception indicating access out of the defined range
|
||||||
@@ -228,12 +235,14 @@ class out_of_range : public exception
|
|||||||
static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
|
static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
|
const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
|
||||||
return {id_, w.c_str()};
|
return { id_, w.c_str() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
out_of_range(int id_, const char* what_arg)
|
||||||
|
: exception(id_, what_arg)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief exception indicating other library errors
|
/// @brief exception indicating other library errors
|
||||||
@@ -245,12 +254,14 @@ class other_error : public exception
|
|||||||
static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
|
static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
|
||||||
{
|
{
|
||||||
const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
|
const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
|
||||||
return {id_, w.c_str()};
|
return { id_, w.c_str() };
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_HEDLEY_NON_NULL(3)
|
JSON_HEDLEY_NON_NULL(3)
|
||||||
other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
other_error(int id_, const char* what_arg)
|
||||||
|
: exception(id_, what_arg)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint8_t
|
#include <cstddef> // size_t
|
||||||
#include <cstddef> // size_t
|
#include <cstdint> // uint8_t
|
||||||
#include <functional> // hash
|
#include <functional> // hash
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/value_t.hpp>
|
#include <nlohmann/detail/value_t.hpp>
|
||||||
@@ -59,7 +59,7 @@ std::size_t hash(const BasicJsonType& j)
|
|||||||
auto seed = combine(type, j.size());
|
auto seed = combine(type, j.size());
|
||||||
for (const auto& element : j.items())
|
for (const auto& element : j.items())
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(element.key());
|
const auto h = std::hash<string_t>{}(element.key());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, hash(element.value()));
|
seed = combine(seed, hash(element.value()));
|
||||||
}
|
}
|
||||||
@@ -78,50 +78,50 @@ std::size_t hash(const BasicJsonType& j)
|
|||||||
|
|
||||||
case BasicJsonType::value_t::string:
|
case BasicJsonType::value_t::string:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
|
const auto h = std::hash<string_t>{}(j.template get_ref<const string_t&>());
|
||||||
return combine(type, h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::boolean:
|
case BasicJsonType::value_t::boolean:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<bool> {}(j.template get<bool>());
|
const auto h = std::hash<bool>{}(j.template get<bool>());
|
||||||
return combine(type, h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::number_integer:
|
case BasicJsonType::value_t::number_integer:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
|
const auto h = std::hash<number_integer_t>{}(j.template get<number_integer_t>());
|
||||||
return combine(type, h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::number_unsigned:
|
case BasicJsonType::value_t::number_unsigned:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
|
const auto h = std::hash<number_unsigned_t>{}(j.template get<number_unsigned_t>());
|
||||||
return combine(type, h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::number_float:
|
case BasicJsonType::value_t::number_float:
|
||||||
{
|
{
|
||||||
const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
|
const auto h = std::hash<number_float_t>{}(j.template get<number_float_t>());
|
||||||
return combine(type, h);
|
return combine(type, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
case BasicJsonType::value_t::binary:
|
case BasicJsonType::value_t::binary:
|
||||||
{
|
{
|
||||||
auto seed = combine(type, j.get_binary().size());
|
auto seed = combine(type, j.get_binary().size());
|
||||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
const auto h = std::hash<bool>{}(j.get_binary().has_subtype());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
|
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
|
||||||
for (const auto byte : j.get_binary())
|
for (const auto byte : j.get_binary())
|
||||||
{
|
{
|
||||||
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
seed = combine(seed, std::hash<std::uint8_t>{}(byte));
|
||||||
}
|
}
|
||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
return 0; // LCOV_EXCL_LINE
|
return 0; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -8,15 +8,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
|
||||||
#include <memory> // shared_ptr, make_shared, addressof
|
#include <memory> // shared_ptr, make_shared, addressof
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string, char_traits
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
|
||||||
#include <utility> // pair, declval
|
#include <utility> // pair, declval
|
||||||
|
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
#include <cstdio> // FILE *
|
#include <cstdio> // FILE *
|
||||||
@@ -32,7 +32,15 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// the supported input formats
|
/// the supported input formats
|
||||||
enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
|
enum class input_format_t
|
||||||
|
{
|
||||||
|
json,
|
||||||
|
cbor,
|
||||||
|
msgpack,
|
||||||
|
ubjson,
|
||||||
|
bson,
|
||||||
|
bjdata
|
||||||
|
};
|
||||||
|
|
||||||
////////////////////
|
////////////////////
|
||||||
// input adapters //
|
// input adapters //
|
||||||
@@ -50,7 +58,7 @@ class file_input_adapter
|
|||||||
|
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
explicit file_input_adapter(std::FILE* f) noexcept
|
explicit file_input_adapter(std::FILE* f) noexcept
|
||||||
: m_file(f)
|
: m_file(f)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(m_file != nullptr);
|
JSON_ASSERT(m_file != nullptr);
|
||||||
}
|
}
|
||||||
@@ -97,7 +105,8 @@ class input_stream_adapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
explicit input_stream_adapter(std::istream& i)
|
explicit input_stream_adapter(std::istream& i)
|
||||||
: is(&i), sb(i.rdbuf())
|
: is(&i)
|
||||||
|
, sb(i.rdbuf())
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
@@ -106,7 +115,8 @@ class input_stream_adapter
|
|||||||
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
|
input_stream_adapter& operator=(input_stream_adapter&&) = delete;
|
||||||
|
|
||||||
input_stream_adapter(input_stream_adapter&& rhs) noexcept
|
input_stream_adapter(input_stream_adapter&& rhs) noexcept
|
||||||
: is(rhs.is), sb(rhs.sb)
|
: is(rhs.is)
|
||||||
|
, sb(rhs.sb)
|
||||||
{
|
{
|
||||||
rhs.is = nullptr;
|
rhs.is = nullptr;
|
||||||
rhs.sb = nullptr;
|
rhs.sb = nullptr;
|
||||||
@@ -142,7 +152,8 @@ class iterator_input_adapter
|
|||||||
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
using char_type = typename std::iterator_traits<IteratorType>::value_type;
|
||||||
|
|
||||||
iterator_input_adapter(IteratorType first, IteratorType last)
|
iterator_input_adapter(IteratorType first, IteratorType last)
|
||||||
: current(std::move(first)), end(std::move(last))
|
: current(std::move(first))
|
||||||
|
, end(std::move(last))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
typename char_traits<char_type>::int_type get_character()
|
typename char_traits<char_type>::int_type get_character()
|
||||||
@@ -177,10 +188,8 @@ template<typename BaseInputAdapter>
|
|||||||
struct wide_string_input_helper<BaseInputAdapter, 4>
|
struct wide_string_input_helper<BaseInputAdapter, 4>
|
||||||
{
|
{
|
||||||
// UTF-32
|
// UTF-32
|
||||||
static void fill_buffer(BaseInputAdapter& input,
|
static void
|
||||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
|
||||||
size_t& utf8_bytes_index,
|
|
||||||
size_t& utf8_bytes_filled)
|
|
||||||
{
|
{
|
||||||
utf8_bytes_index = 0;
|
utf8_bytes_index = 0;
|
||||||
|
|
||||||
@@ -235,10 +244,8 @@ template<typename BaseInputAdapter>
|
|||||||
struct wide_string_input_helper<BaseInputAdapter, 2>
|
struct wide_string_input_helper<BaseInputAdapter, 2>
|
||||||
{
|
{
|
||||||
// UTF-16
|
// UTF-16
|
||||||
static void fill_buffer(BaseInputAdapter& input,
|
static void
|
||||||
std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
|
fill_buffer(BaseInputAdapter& input, std::array<std::char_traits<char>::int_type, 4>& utf8_bytes, size_t& utf8_bytes_index, size_t& utf8_bytes_filled)
|
||||||
size_t& utf8_bytes_index,
|
|
||||||
size_t& utf8_bytes_filled)
|
|
||||||
{
|
{
|
||||||
utf8_bytes_index = 0;
|
utf8_bytes_index = 0;
|
||||||
|
|
||||||
@@ -301,7 +308,8 @@ class wide_string_input_adapter
|
|||||||
using char_type = char;
|
using char_type = char;
|
||||||
|
|
||||||
wide_string_input_adapter(BaseInputAdapter base)
|
wide_string_input_adapter(BaseInputAdapter base)
|
||||||
: base_adapter(base) {}
|
: base_adapter(base)
|
||||||
|
{}
|
||||||
|
|
||||||
typename std::char_traits<char>::int_type get_character() noexcept
|
typename std::char_traits<char>::int_type get_character() noexcept
|
||||||
{
|
{
|
||||||
@@ -330,7 +338,7 @@ class wide_string_input_adapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// a buffer for UTF-8 bytes
|
/// a buffer for UTF-8 bytes
|
||||||
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
|
std::array<std::char_traits<char>::int_type, 4> utf8_bytes = { { 0, 0, 0, 0 } };
|
||||||
|
|
||||||
/// index to the utf8_codes array for the next valid byte
|
/// index to the utf8_codes array for the next valid byte
|
||||||
std::size_t utf8_bytes_index = 0;
|
std::size_t utf8_bytes_index = 0;
|
||||||
@@ -394,19 +402,19 @@ using std::begin;
|
|||||||
using std::end;
|
using std::end;
|
||||||
|
|
||||||
template<typename ContainerType, typename Enable = void>
|
template<typename ContainerType, typename Enable = void>
|
||||||
struct container_input_adapter_factory {};
|
struct container_input_adapter_factory
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename ContainerType>
|
template<typename ContainerType>
|
||||||
struct container_input_adapter_factory< ContainerType,
|
struct container_input_adapter_factory<ContainerType, void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
|
||||||
void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
|
|
||||||
{
|
|
||||||
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
|
|
||||||
|
|
||||||
static adapter_type create(const ContainerType& container)
|
|
||||||
{
|
{
|
||||||
return input_adapter(begin(container), end(container));
|
using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
|
||||||
}
|
|
||||||
};
|
static adapter_type create(const ContainerType& container)
|
||||||
|
{
|
||||||
|
return input_adapter(begin(container), end(container));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace container_input_adapter_factory_impl
|
} // namespace container_input_adapter_factory_impl
|
||||||
|
|
||||||
@@ -437,13 +445,11 @@ inline input_stream_adapter input_adapter(std::istream&& stream)
|
|||||||
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
|
using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
|
||||||
|
|
||||||
// Null-delimited strings, and the like.
|
// Null-delimited strings, and the like.
|
||||||
template < typename CharT,
|
template<
|
||||||
typename std::enable_if <
|
typename CharT,
|
||||||
std::is_pointer<CharT>::value&&
|
typename std::enable_if<std::is_pointer<CharT>::value && !std::is_array<CharT>::value &&
|
||||||
!std::is_array<CharT>::value&&
|
std::is_integral<typename std::remove_pointer<CharT>::type>::value && sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
int>::type = 0>
|
||||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
|
||||||
int >::type = 0 >
|
|
||||||
contiguous_bytes_input_adapter input_adapter(CharT b)
|
contiguous_bytes_input_adapter input_adapter(CharT b)
|
||||||
{
|
{
|
||||||
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
auto length = std::strlen(reinterpret_cast<const char*>(b));
|
||||||
@@ -452,7 +458,8 @@ contiguous_bytes_input_adapter input_adapter(CharT b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, std::size_t N>
|
template<typename T, std::size_t N>
|
||||||
auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
auto input_adapter(T (&array)[N])
|
||||||
|
-> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
{
|
{
|
||||||
return input_adapter(array, array + N);
|
return input_adapter(array, array + N);
|
||||||
}
|
}
|
||||||
@@ -463,25 +470,24 @@ auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) /
|
|||||||
class span_input_adapter
|
class span_input_adapter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template < typename CharT,
|
template<typename CharT,
|
||||||
typename std::enable_if <
|
typename std::enable_if<std::is_pointer<CharT>::value && std::is_integral<typename std::remove_pointer<CharT>::type>::value &&
|
||||||
std::is_pointer<CharT>::value&&
|
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
||||||
std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
|
int>::type = 0>
|
||||||
sizeof(typename std::remove_pointer<CharT>::type) == 1,
|
|
||||||
int >::type = 0 >
|
|
||||||
span_input_adapter(CharT b, std::size_t l)
|
span_input_adapter(CharT b, std::size_t l)
|
||||||
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
|
: ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l)
|
||||||
|
{}
|
||||||
|
|
||||||
template<class IteratorType,
|
template<
|
||||||
typename std::enable_if<
|
class IteratorType,
|
||||||
std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
|
typename std::enable_if<std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value, int>::type = 0>
|
||||||
int>::type = 0>
|
|
||||||
span_input_adapter(IteratorType first, IteratorType last)
|
span_input_adapter(IteratorType first, IteratorType last)
|
||||||
: ia(input_adapter(first, last)) {}
|
: ia(input_adapter(first, last))
|
||||||
|
{}
|
||||||
|
|
||||||
contiguous_bytes_input_adapter&& get()
|
contiguous_bytes_input_adapter&& get()
|
||||||
{
|
{
|
||||||
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -130,9 +130,7 @@ struct json_sax
|
|||||||
@param[in] ex an exception object describing the error
|
@param[in] ex an exception object describing the error
|
||||||
@return whether parsing should proceed (must return false)
|
@return whether parsing should proceed (must return false)
|
||||||
*/
|
*/
|
||||||
virtual bool parse_error(std::size_t position,
|
virtual bool parse_error(std::size_t position, const std::string& last_token, const detail::exception& ex) = 0;
|
||||||
const std::string& last_token,
|
|
||||||
const detail::exception& ex) = 0;
|
|
||||||
|
|
||||||
json_sax() = default;
|
json_sax() = default;
|
||||||
json_sax(const json_sax&) = default;
|
json_sax(const json_sax&) = default;
|
||||||
@@ -173,14 +171,15 @@ class json_sax_dom_parser
|
|||||||
@param[in] allow_exceptions_ whether parse errors yield exceptions
|
@param[in] allow_exceptions_ whether parse errors yield exceptions
|
||||||
*/
|
*/
|
||||||
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
|
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
|
||||||
: root(r), allow_exceptions(allow_exceptions_)
|
: root(r)
|
||||||
|
, allow_exceptions(allow_exceptions_)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// make class move-only
|
// make class move-only
|
||||||
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
|
json_sax_dom_parser(const json_sax_dom_parser&) = delete;
|
||||||
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
|
json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
|
||||||
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
~json_sax_dom_parser() = default;
|
~json_sax_dom_parser() = default;
|
||||||
|
|
||||||
bool null()
|
bool null()
|
||||||
@@ -280,8 +279,7 @@ class json_sax_dom_parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Exception>
|
template<class Exception>
|
||||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
|
||||||
const Exception& ex)
|
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
static_cast<void>(ex);
|
static_cast<void>(ex);
|
||||||
@@ -305,8 +303,7 @@ class json_sax_dom_parser
|
|||||||
object to which we can add elements
|
object to which we can add elements
|
||||||
*/
|
*/
|
||||||
template<typename Value>
|
template<typename Value>
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
JSON_HEDLEY_RETURNS_NON_NULL BasicJsonType* handle_value(Value&& v)
|
||||||
BasicJsonType* handle_value(Value&& v)
|
|
||||||
{
|
{
|
||||||
if (ref_stack.empty())
|
if (ref_stack.empty())
|
||||||
{
|
{
|
||||||
@@ -331,7 +328,7 @@ class json_sax_dom_parser
|
|||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// stack to model hierarchy of values
|
||||||
std::vector<BasicJsonType*> ref_stack {};
|
std::vector<BasicJsonType*> ref_stack{};
|
||||||
/// helper to hold the reference for the next object element
|
/// helper to hold the reference for the next object element
|
||||||
BasicJsonType* object_element = nullptr;
|
BasicJsonType* object_element = nullptr;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
@@ -352,19 +349,19 @@ class json_sax_dom_callback_parser
|
|||||||
using parser_callback_t = typename BasicJsonType::parser_callback_t;
|
using parser_callback_t = typename BasicJsonType::parser_callback_t;
|
||||||
using parse_event_t = typename BasicJsonType::parse_event_t;
|
using parse_event_t = typename BasicJsonType::parse_event_t;
|
||||||
|
|
||||||
json_sax_dom_callback_parser(BasicJsonType& r,
|
json_sax_dom_callback_parser(BasicJsonType& r, const parser_callback_t cb, const bool allow_exceptions_ = true)
|
||||||
const parser_callback_t cb,
|
: root(r)
|
||||||
const bool allow_exceptions_ = true)
|
, callback(cb)
|
||||||
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
|
, allow_exceptions(allow_exceptions_)
|
||||||
{
|
{
|
||||||
keep_stack.push_back(true);
|
keep_stack.push_back(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// make class move-only
|
// make class move-only
|
||||||
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
|
json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
|
||||||
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
|
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; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
~json_sax_dom_callback_parser() = default;
|
~json_sax_dom_callback_parser() = default;
|
||||||
|
|
||||||
bool null()
|
bool null()
|
||||||
@@ -530,8 +527,7 @@ class json_sax_dom_callback_parser
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Exception>
|
template<class Exception>
|
||||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
|
||||||
const Exception& ex)
|
|
||||||
{
|
{
|
||||||
errored = true;
|
errored = true;
|
||||||
static_cast<void>(ex);
|
static_cast<void>(ex);
|
||||||
@@ -572,7 +568,7 @@ class json_sax_dom_callback_parser
|
|||||||
// container
|
// container
|
||||||
if (!keep_stack.back())
|
if (!keep_stack.back())
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return { false, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
// create value
|
// create value
|
||||||
@@ -584,20 +580,20 @@ class json_sax_dom_callback_parser
|
|||||||
// do not handle this value if we just learnt it shall be discarded
|
// do not handle this value if we just learnt it shall be discarded
|
||||||
if (!keep)
|
if (!keep)
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return { false, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ref_stack.empty())
|
if (ref_stack.empty())
|
||||||
{
|
{
|
||||||
root = std::move(value);
|
root = std::move(value);
|
||||||
return {true, & root};
|
return { true, &root };
|
||||||
}
|
}
|
||||||
|
|
||||||
// skip this value if we already decided to skip the parent
|
// skip this value if we already decided to skip the parent
|
||||||
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
|
// (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
|
||||||
if (!ref_stack.back())
|
if (!ref_stack.back())
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return { false, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
// we now only expect arrays and objects
|
// we now only expect arrays and objects
|
||||||
@@ -607,7 +603,7 @@ class json_sax_dom_callback_parser
|
|||||||
if (ref_stack.back()->is_array())
|
if (ref_stack.back()->is_array())
|
||||||
{
|
{
|
||||||
ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
|
ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
|
||||||
return {true, & (ref_stack.back()->m_data.m_value.array->back())};
|
return { true, &(ref_stack.back()->m_data.m_value.array->back()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
// object
|
// object
|
||||||
@@ -619,22 +615,22 @@ class json_sax_dom_callback_parser
|
|||||||
|
|
||||||
if (!store_element)
|
if (!store_element)
|
||||||
{
|
{
|
||||||
return {false, nullptr};
|
return { false, nullptr };
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_ASSERT(object_element);
|
JSON_ASSERT(object_element);
|
||||||
*object_element = std::move(value);
|
*object_element = std::move(value);
|
||||||
return {true, object_element};
|
return { true, object_element };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// stack to model hierarchy of values
|
||||||
std::vector<BasicJsonType*> ref_stack {};
|
std::vector<BasicJsonType*> ref_stack{};
|
||||||
/// stack to manage which values to keep
|
/// stack to manage which values to keep
|
||||||
std::vector<bool> keep_stack {};
|
std::vector<bool> keep_stack{};
|
||||||
/// stack to manage which object keys to keep
|
/// stack to manage which object keys to keep
|
||||||
std::vector<bool> key_keep_stack {};
|
std::vector<bool> key_keep_stack{};
|
||||||
/// helper to hold the reference for the next object element
|
/// helper to hold the reference for the next object element
|
||||||
BasicJsonType* object_element = nullptr;
|
BasicJsonType* object_element = nullptr;
|
||||||
/// whether a syntax error occurred
|
/// whether a syntax error occurred
|
||||||
|
|||||||
@@ -8,15 +8,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <clocale> // localeconv
|
#include <clocale> // localeconv
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <string> // char_traits, string
|
#include <string> // char_traits, string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
#include <nlohmann/detail/input/position_t.hpp>
|
#include <nlohmann/detail/input/position_t.hpp>
|
||||||
@@ -97,7 +97,7 @@ class lexer_base
|
|||||||
case token_type::literal_or_value:
|
case token_type::literal_or_value:
|
||||||
return "'[', '{', or a literal";
|
return "'[', '{', or a literal";
|
||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
default: // catch non-enum values
|
default: // catch non-enum values
|
||||||
return "unknown token";
|
return "unknown token";
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
@@ -122,16 +122,16 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
using token_type = typename lexer_base<BasicJsonType>::token_type;
|
using token_type = typename lexer_base<BasicJsonType>::token_type;
|
||||||
|
|
||||||
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
|
explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
|
||||||
: ia(std::move(adapter))
|
: ia(std::move(adapter))
|
||||||
, ignore_comments(ignore_comments_)
|
, ignore_comments(ignore_comments_)
|
||||||
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
|
, decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
lexer(const lexer&) = delete;
|
lexer(const lexer&) = delete;
|
||||||
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
lexer& operator=(lexer&) = delete;
|
lexer& operator=(lexer&) = delete;
|
||||||
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||||
~lexer() = default;
|
~lexer() = default;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -223,7 +223,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
for (auto range = ranges.begin(); range != ranges.end(); ++range)
|
for (auto range = ranges.begin(); range != ranges.end(); ++range)
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
|
if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
|
||||||
{
|
{
|
||||||
add(current);
|
add(current);
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
const int codepoint1 = get_codepoint();
|
const int codepoint1 = get_codepoint();
|
||||||
int codepoint = codepoint1; // start with codepoint1
|
int codepoint = codepoint1; // start with codepoint1
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
|
if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
|
||||||
{
|
{
|
||||||
@@ -347,14 +347,14 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
{
|
{
|
||||||
// overwrite codepoint
|
// overwrite codepoint
|
||||||
codepoint = static_cast<int>(
|
codepoint = static_cast<int>(
|
||||||
// high surrogate occupies the most significant 22 bits
|
// high surrogate occupies the most significant 22 bits
|
||||||
(static_cast<unsigned int>(codepoint1) << 10u)
|
(static_cast<unsigned int>(codepoint1) << 10u)
|
||||||
// low surrogate occupies the least significant 15 bits
|
// low surrogate occupies the least significant 15 bits
|
||||||
+ static_cast<unsigned int>(codepoint2)
|
+ static_cast<unsigned int>(codepoint2)
|
||||||
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
// there is still the 0xD800, 0xDC00 and 0x10000 noise
|
||||||
// in the result, so we have to subtract with:
|
// in the result, so we have to subtract with:
|
||||||
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
// (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
|
||||||
- 0x35FDC00u);
|
- 0x35FDC00u);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -745,7 +745,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
case 0xDE:
|
case 0xDE:
|
||||||
case 0xDF:
|
case 0xDF:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
|
if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({ 0x80, 0xBF })))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -755,7 +755,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
|
// U+0800..U+0FFF: bytes E0 A0..BF 80..BF
|
||||||
case 0xE0:
|
case 0xE0:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0xA0, 0xBF, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -779,7 +779,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
case 0xEE:
|
case 0xEE:
|
||||||
case 0xEF:
|
case 0xEF:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -789,7 +789,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
|
// U+D000..U+D7FF: bytes ED 80..9F 80..BF
|
||||||
case 0xED:
|
case 0xED:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x9F, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -799,7 +799,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
// U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
|
||||||
case 0xF0:
|
case 0xF0:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -811,7 +811,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
case 0xF2:
|
case 0xF2:
|
||||||
case 0xF3:
|
case 0xF3:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -821,7 +821,7 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
|
// U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
|
||||||
case 0xF4:
|
case 0xF4:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
|
if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({ 0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF }))))
|
||||||
{
|
{
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
@@ -1006,8 +1006,8 @@ class lexer : public lexer_base<BasicJsonType>
|
|||||||
}
|
}
|
||||||
|
|
||||||
// all other characters are rejected outside scan_number()
|
// all other characters are rejected outside scan_number()
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
scan_number_minus:
|
scan_number_minus:
|
||||||
@@ -1185,8 +1185,7 @@ scan_number_exponent:
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
error_message =
|
error_message = "invalid number; expected '+', '-', or digit after exponent";
|
||||||
"invalid number; expected '+', '-', or digit after exponent";
|
|
||||||
return token_type::parse_error;
|
return token_type::parse_error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1245,7 +1244,7 @@ scan_number_done:
|
|||||||
// we are done scanning a number)
|
// we are done scanning a number)
|
||||||
unget();
|
unget();
|
||||||
|
|
||||||
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
// try to parse integers first and fall back to floats
|
// try to parse integers first and fall back to floats
|
||||||
@@ -1298,8 +1297,7 @@ scan_number_done:
|
|||||||
@param[in] return_type the token type to return on success
|
@param[in] return_type the token type to return on success
|
||||||
*/
|
*/
|
||||||
JSON_HEDLEY_NON_NULL(2)
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
token_type scan_literal(const char_type* literal_text, const std::size_t length,
|
token_type scan_literal(const char_type* literal_text, const std::size_t length, token_type return_type)
|
||||||
token_type return_type)
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
|
JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
|
||||||
for (std::size_t i = 1; i < length; ++i)
|
for (std::size_t i = 1; i < length; ++i)
|
||||||
@@ -1455,8 +1453,9 @@ scan_number_done:
|
|||||||
if (static_cast<unsigned char>(c) <= '\x1F')
|
if (static_cast<unsigned char>(c) <= '\x1F')
|
||||||
{
|
{
|
||||||
// escape control characters
|
// escape control characters
|
||||||
std::array<char, 9> cs{{}};
|
std::array<char, 9> cs{ {} };
|
||||||
static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
static_cast<void>(( // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c)));
|
||||||
result += cs.data();
|
result += cs.data();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -1503,8 +1502,7 @@ scan_number_done:
|
|||||||
do
|
do
|
||||||
{
|
{
|
||||||
get();
|
get();
|
||||||
}
|
} while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
|
||||||
while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
token_type scan()
|
token_type scan()
|
||||||
@@ -1550,17 +1548,25 @@ scan_number_done:
|
|||||||
// literals
|
// literals
|
||||||
case 't':
|
case 't':
|
||||||
{
|
{
|
||||||
std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
|
std::array<char_type, 4> true_literal = {
|
||||||
|
{ static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e') }
|
||||||
|
};
|
||||||
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
|
return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
|
||||||
}
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
|
std::array<char_type, 5> false_literal = { { static_cast<char_type>('f'),
|
||||||
|
static_cast<char_type>('a'),
|
||||||
|
static_cast<char_type>('l'),
|
||||||
|
static_cast<char_type>('s'),
|
||||||
|
static_cast<char_type>('e') } };
|
||||||
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
|
return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
|
||||||
}
|
}
|
||||||
case 'n':
|
case 'n':
|
||||||
{
|
{
|
||||||
std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
|
std::array<char_type, 4> null_literal = {
|
||||||
|
{ static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l') }
|
||||||
|
};
|
||||||
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
|
return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,13 +1615,13 @@ scan_number_done:
|
|||||||
bool next_unget = false;
|
bool next_unget = false;
|
||||||
|
|
||||||
/// the start position of the current token
|
/// the start position of the current token
|
||||||
position_t position {};
|
position_t position{};
|
||||||
|
|
||||||
/// raw input token string (for error messages)
|
/// raw input token string (for error messages)
|
||||||
std::vector<char_type> token_string {};
|
std::vector<char_type> token_string{};
|
||||||
|
|
||||||
/// buffer for variable-length tokens (numbers, strings)
|
/// buffer for variable-length tokens (numbers, strings)
|
||||||
string_t token_buffer {};
|
string_t token_buffer{};
|
||||||
|
|
||||||
/// a description of occurred lexer errors
|
/// a description of occurred lexer errors
|
||||||
const char* error_message = "";
|
const char* error_message = "";
|
||||||
|
|||||||
@@ -8,12 +8,12 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cmath> // isfinite
|
#include <cmath> // isfinite
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <functional> // function
|
#include <functional> // function
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/input/input_adapters.hpp>
|
#include <nlohmann/detail/input/input_adapters.hpp>
|
||||||
@@ -48,8 +48,7 @@ enum class parse_event_t : std::uint8_t
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
using parser_callback_t =
|
using parser_callback_t = std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
||||||
std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief syntax analysis
|
@brief syntax analysis
|
||||||
@@ -72,9 +71,9 @@ class parser
|
|||||||
const parser_callback_t<BasicJsonType> cb = nullptr,
|
const parser_callback_t<BasicJsonType> cb = nullptr,
|
||||||
const bool allow_exceptions_ = true,
|
const bool allow_exceptions_ = true,
|
||||||
const bool skip_comments = false)
|
const bool skip_comments = false)
|
||||||
: callback(cb)
|
: callback(cb)
|
||||||
, m_lexer(std::move(adapter), skip_comments)
|
, m_lexer(std::move(adapter), skip_comments)
|
||||||
, allow_exceptions(allow_exceptions_)
|
, allow_exceptions(allow_exceptions_)
|
||||||
{
|
{
|
||||||
// read first token
|
// read first token
|
||||||
get_token();
|
get_token();
|
||||||
@@ -102,8 +101,7 @@ class parser
|
|||||||
{
|
{
|
||||||
sdp.parse_error(m_lexer.get_position(),
|
sdp.parse_error(m_lexer.get_position(),
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_token_string(),
|
||||||
parse_error::create(101, m_lexer.get_position(),
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
|
||||||
exception_message(token_type::end_of_input, "value"), nullptr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// in case of an error, return discarded value
|
// in case of an error, return discarded value
|
||||||
@@ -160,7 +158,7 @@ class parser
|
|||||||
JSON_HEDLEY_NON_NULL(2)
|
JSON_HEDLEY_NON_NULL(2)
|
||||||
bool sax_parse(SAX* sax, const bool strict = true)
|
bool sax_parse(SAX* sax, const bool strict = true)
|
||||||
{
|
{
|
||||||
(void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
|
(void)detail::is_sax_static_asserts<SAX, BasicJsonType>{};
|
||||||
const bool result = sax_parse_internal(sax);
|
const bool result = sax_parse_internal(sax);
|
||||||
|
|
||||||
// strict mode: next byte must be EOF
|
// strict mode: next byte must be EOF
|
||||||
@@ -212,9 +210,10 @@ class parser
|
|||||||
// parse key
|
// parse key
|
||||||
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
|
if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
||||||
}
|
}
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||||
{
|
{
|
||||||
@@ -224,9 +223,10 @@ class parser
|
|||||||
// parse separator (:)
|
// parse separator (:)
|
||||||
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// remember we are now inside an object
|
// remember we are now inside an object
|
||||||
@@ -337,23 +337,28 @@ class parser
|
|||||||
case token_type::parse_error:
|
case token_type::parse_error:
|
||||||
{
|
{
|
||||||
// using "uninitialized" to avoid "expected" message
|
// using "uninitialized" to avoid "expected" message
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
|
||||||
}
|
}
|
||||||
case token_type::end_of_input:
|
case token_type::end_of_input:
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
|
if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(),
|
m_lexer.get_token_string(),
|
||||||
"attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
|
parse_error::create(101,
|
||||||
|
m_lexer.get_position(),
|
||||||
|
"attempting to parse an empty input; check that your input string or stream contains the expected JSON",
|
||||||
|
nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
||||||
}
|
}
|
||||||
case token_type::uninitialized:
|
case token_type::uninitialized:
|
||||||
case token_type::end_array:
|
case token_type::end_array:
|
||||||
@@ -361,11 +366,12 @@ class parser
|
|||||||
case token_type::name_separator:
|
case token_type::name_separator:
|
||||||
case token_type::value_separator:
|
case token_type::value_separator:
|
||||||
case token_type::literal_or_value:
|
case token_type::literal_or_value:
|
||||||
default: // the last token was unexpected
|
default: // the last token was unexpected
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -422,9 +428,10 @@ class parser
|
|||||||
// parse key
|
// parse key
|
||||||
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
|
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
|
||||||
@@ -435,9 +442,10 @@ class parser
|
|||||||
// parse separator (:)
|
// parse separator (:)
|
||||||
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
|
||||||
{
|
{
|
||||||
return sax->parse_error(m_lexer.get_position(),
|
return sax->parse_error(
|
||||||
m_lexer.get_token_string(),
|
m_lexer.get_position(),
|
||||||
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
m_lexer.get_token_string(),
|
||||||
|
parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse values
|
// parse values
|
||||||
@@ -488,8 +496,7 @@ class parser
|
|||||||
|
|
||||||
if (last_token == token_type::parse_error)
|
if (last_token == token_type::parse_error)
|
||||||
{
|
{
|
||||||
error_msg += concat(m_lexer.get_error_message(), "; last read: '",
|
error_msg += concat(m_lexer.get_error_message(), "; last read: '", m_lexer.get_token_string(), '\'');
|
||||||
m_lexer.get_token_string(), '\'');
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
|
|||||||
@@ -21,14 +21,15 @@ namespace detail
|
|||||||
@note This structure could easily be a union, but MSVC currently does not allow
|
@note This structure could easily be a union, but MSVC currently does not allow
|
||||||
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
|
unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
|
||||||
*/
|
*/
|
||||||
template<typename BasicJsonType> struct internal_iterator
|
template<typename BasicJsonType>
|
||||||
|
struct internal_iterator
|
||||||
{
|
{
|
||||||
/// iterator for JSON objects
|
/// iterator for JSON objects
|
||||||
typename BasicJsonType::object_t::iterator object_iterator {};
|
typename BasicJsonType::object_t::iterator object_iterator{};
|
||||||
/// iterator for JSON arrays
|
/// iterator for JSON arrays
|
||||||
typename BasicJsonType::array_t::iterator array_iterator {};
|
typename BasicJsonType::array_t::iterator array_iterator{};
|
||||||
/// generic iterator for all other types
|
/// generic iterator for all other types
|
||||||
primitive_iterator_t primitive_iterator {};
|
primitive_iterator_t primitive_iterator{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
|
#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
|
||||||
#include <type_traits> // conditional, is_const, remove_const
|
#include <type_traits> // conditional, is_const, remove_const
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
#include <nlohmann/detail/iterators/internal_iterator.hpp>
|
||||||
@@ -24,8 +24,10 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
// forward declare, to be able to friend it later on
|
// forward declare, to be able to friend it later on
|
||||||
template<typename IteratorType> class iteration_proxy;
|
template<typename IteratorType>
|
||||||
template<typename IteratorType> class iteration_proxy_value;
|
class iteration_proxy;
|
||||||
|
template<typename IteratorType>
|
||||||
|
class iteration_proxy_value;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief a template for a bidirectional iterator for the @ref basic_json class
|
@brief a template for a bidirectional iterator for the @ref basic_json class
|
||||||
@@ -44,10 +46,11 @@ This class implements a both iterators (iterator and const_iterator) for the
|
|||||||
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
|
iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
|
||||||
*/
|
*/
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
||||||
{
|
{
|
||||||
/// the iterator with BasicJsonType of different const-ness
|
/// the iterator with BasicJsonType of different const-ness
|
||||||
using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
|
using other_iter_impl =
|
||||||
|
iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
|
||||||
/// allow basic_json to access private members
|
/// allow basic_json to access private members
|
||||||
friend other_iter_impl;
|
friend other_iter_impl;
|
||||||
friend BasicJsonType;
|
friend BasicJsonType;
|
||||||
@@ -57,11 +60,10 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
using object_t = typename BasicJsonType::object_t;
|
using object_t = typename BasicJsonType::object_t;
|
||||||
using array_t = typename BasicJsonType::array_t;
|
using array_t = typename BasicJsonType::array_t;
|
||||||
// make sure BasicJsonType is basic_json or const basic_json
|
// make sure BasicJsonType is basic_json or const basic_json
|
||||||
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
|
static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value, "iter_impl only accepts (const) basic_json");
|
||||||
"iter_impl only accepts (const) basic_json");
|
|
||||||
// superficial check for the LegacyBidirectionalIterator named requirement
|
// superficial check for the LegacyBidirectionalIterator named requirement
|
||||||
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
|
static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value &&
|
||||||
&& std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
|
std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
|
||||||
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
|
"basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -77,14 +79,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
/// a type to represent differences between iterators
|
/// a type to represent differences between iterators
|
||||||
using difference_type = typename BasicJsonType::difference_type;
|
using difference_type = typename BasicJsonType::difference_type;
|
||||||
/// defines a pointer to the type iterated over (value_type)
|
/// defines a pointer to the type iterated over (value_type)
|
||||||
using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
|
using pointer =
|
||||||
typename BasicJsonType::const_pointer,
|
typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_pointer, typename BasicJsonType::pointer>::type;
|
||||||
typename BasicJsonType::pointer>::type;
|
|
||||||
/// defines a reference to the type iterated over (value_type)
|
/// defines a reference to the type iterated over (value_type)
|
||||||
using reference =
|
using reference =
|
||||||
typename std::conditional<std::is_const<BasicJsonType>::value,
|
typename std::conditional<std::is_const<BasicJsonType>::value, typename BasicJsonType::const_reference, typename BasicJsonType::reference>::type;
|
||||||
typename BasicJsonType::const_reference,
|
|
||||||
typename BasicJsonType::reference>::type;
|
|
||||||
|
|
||||||
iter_impl() = default;
|
iter_impl() = default;
|
||||||
~iter_impl() = default;
|
~iter_impl() = default;
|
||||||
@@ -97,7 +96,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@pre object != nullptr
|
@pre object != nullptr
|
||||||
@post The iterator is initialized; i.e. `m_object != nullptr`.
|
@post The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
*/
|
*/
|
||||||
explicit iter_impl(pointer object) noexcept : m_object(object)
|
explicit iter_impl(pointer object) noexcept
|
||||||
|
: m_object(object)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(m_object != nullptr);
|
JSON_ASSERT(m_object != nullptr);
|
||||||
|
|
||||||
@@ -148,7 +148,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
information refer to: https://github.com/nlohmann/json/issues/1608
|
information refer to: https://github.com/nlohmann/json/issues/1608
|
||||||
*/
|
*/
|
||||||
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
|
iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
|
||||||
: m_object(other.m_object), m_it(other.m_it)
|
: m_object(other.m_object)
|
||||||
|
, m_it(other.m_it)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -173,7 +174,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@note It is not checked whether @a other is initialized.
|
@note It is not checked whether @a other is initialized.
|
||||||
*/
|
*/
|
||||||
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
|
iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
|
||||||
: m_object(other.m_object), m_it(other.m_it)
|
: m_object(other.m_object)
|
||||||
|
, m_it(other.m_it)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -182,14 +184,14 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@return const/non-const iterator
|
@return const/non-const iterator
|
||||||
@note It is not checked whether @a other is initialized.
|
@note It is not checked whether @a other is initialized.
|
||||||
*/
|
*/
|
||||||
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
|
iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
|
||||||
{
|
{
|
||||||
m_object = other.m_object;
|
m_object = other.m_object;
|
||||||
m_it = other.m_it;
|
m_it = other.m_it;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_PRIVATE_UNLESS_TESTED:
|
JSON_PRIVATE_UNLESS_TESTED :
|
||||||
/*!
|
/*!
|
||||||
@brief set the iterator to the first value
|
@brief set the iterator to the first value
|
||||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
@@ -363,7 +365,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@brief post-increment (it++)
|
@brief post-increment (it++)
|
||||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
*/
|
*/
|
||||||
iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
|
iter_impl operator++(int) & // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
auto result = *this;
|
auto result = *this;
|
||||||
++(*this);
|
++(*this);
|
||||||
@@ -414,7 +416,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@brief post-decrement (it--)
|
@brief post-decrement (it--)
|
||||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
*/
|
*/
|
||||||
iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
|
iter_impl operator--(int) & // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
auto result = *this;
|
auto result = *this;
|
||||||
--(*this);
|
--(*this);
|
||||||
@@ -465,7 +467,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@brief comparison: equal
|
@brief comparison: equal
|
||||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
*/
|
*/
|
||||||
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
|
template<typename IterImpl,
|
||||||
|
detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t> = nullptr>
|
||||||
bool operator==(const IterImpl& other) const
|
bool operator==(const IterImpl& other) const
|
||||||
{
|
{
|
||||||
// if objects are not the same, the comparison is undefined
|
// if objects are not the same, the comparison is undefined
|
||||||
@@ -501,7 +504,8 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
@brief comparison: not equal
|
@brief comparison: not equal
|
||||||
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
@pre The iterator is initialized; i.e. `m_object != nullptr`.
|
||||||
*/
|
*/
|
||||||
template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
|
template<typename IterImpl,
|
||||||
|
detail::enable_if_t<(std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t> = nullptr>
|
||||||
bool operator!=(const IterImpl& other) const
|
bool operator!=(const IterImpl& other) const
|
||||||
{
|
{
|
||||||
return !operator==(other);
|
return !operator==(other);
|
||||||
@@ -548,7 +552,7 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
*/
|
*/
|
||||||
bool operator<=(const iter_impl& other) const
|
bool operator<=(const iter_impl& other) const
|
||||||
{
|
{
|
||||||
return !other.operator < (*this);
|
return !other.operator<(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -740,11 +744,11 @@ class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-speci
|
|||||||
return operator*();
|
return operator*();
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_PRIVATE_UNLESS_TESTED:
|
JSON_PRIVATE_UNLESS_TESTED :
|
||||||
/// associated JSON instance
|
/// associated JSON instance
|
||||||
pointer m_object = nullptr;
|
pointer m_object = nullptr;
|
||||||
/// the actual iterator of the associated instance
|
/// the actual iterator of the associated instance
|
||||||
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
|
internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iterator> // input_iterator_tag
|
#include <iterator> // input_iterator_tag
|
||||||
#include <string> // string, to_string
|
#include <string> // string, to_string
|
||||||
#include <tuple> // tuple_size, get, tuple_element
|
#include <tuple> // tuple_size, get, tuple_element
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
#if JSON_HAS_RANGES
|
#if JSON_HAS_RANGES
|
||||||
#include <ranges> // enable_borrowed_range
|
#include <ranges> // enable_borrowed_range
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
@@ -27,21 +27,22 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
template<typename string_type>
|
template<typename string_type>
|
||||||
void int_to_string( string_type& target, std::size_t value )
|
void int_to_string(string_type& target, std::size_t value)
|
||||||
{
|
{
|
||||||
// For ADL
|
// For ADL
|
||||||
using std::to_string;
|
using std::to_string;
|
||||||
target = to_string(value);
|
target = to_string(value);
|
||||||
}
|
}
|
||||||
template<typename IteratorType> class iteration_proxy_value
|
template<typename IteratorType>
|
||||||
|
class iteration_proxy_value
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
using value_type = iteration_proxy_value;
|
using value_type = iteration_proxy_value;
|
||||||
using pointer = value_type *;
|
using pointer = value_type*;
|
||||||
using reference = value_type &;
|
using reference = value_type&;
|
||||||
using iterator_category = std::input_iterator_tag;
|
using iterator_category = std::input_iterator_tag;
|
||||||
using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
|
using string_type = typename std::remove_cv<typename std::remove_reference<decltype(std::declval<IteratorType>().key())>::type>::type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// the iterator
|
/// the iterator
|
||||||
@@ -57,22 +58,21 @@ template<typename IteratorType> class iteration_proxy_value
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit iteration_proxy_value() = default;
|
explicit iteration_proxy_value() = default;
|
||||||
explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
|
explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0) noexcept(std::is_nothrow_move_constructible<IteratorType>::value &&
|
||||||
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
|
std::is_nothrow_default_constructible<string_type>::value)
|
||||||
&& std::is_nothrow_default_constructible<string_type>::value)
|
: anchor(std::move(it))
|
||||||
: anchor(std::move(it))
|
, array_index(array_index_)
|
||||||
, array_index(array_index_)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
iteration_proxy_value(iteration_proxy_value const&) = default;
|
iteration_proxy_value(iteration_proxy_value const&) = default;
|
||||||
iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
|
iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
|
||||||
// older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
|
// older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
|
||||||
iteration_proxy_value(iteration_proxy_value&&)
|
iteration_proxy_value(iteration_proxy_value&&) noexcept(std::is_nothrow_move_constructible<IteratorType>::value &&
|
||||||
noexcept(std::is_nothrow_move_constructible<IteratorType>::value
|
std::is_nothrow_move_constructible<string_type>::value) =
|
||||||
&& std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
|
default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
|
||||||
iteration_proxy_value& operator=(iteration_proxy_value&&)
|
iteration_proxy_value& operator=(iteration_proxy_value&&) noexcept(std::is_nothrow_move_assignable<IteratorType>::value &&
|
||||||
noexcept(std::is_nothrow_move_assignable<IteratorType>::value
|
std::is_nothrow_move_assignable<string_type>::value) =
|
||||||
&& std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
|
default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
|
||||||
~iteration_proxy_value() = default;
|
~iteration_proxy_value() = default;
|
||||||
|
|
||||||
/// dereference operator (needed for range-based for)
|
/// dereference operator (needed for range-based for)
|
||||||
@@ -90,7 +90,7 @@ template<typename IteratorType> class iteration_proxy_value
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
|
iteration_proxy_value operator++(int) & // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
auto tmp = iteration_proxy_value(anchor, array_index);
|
auto tmp = iteration_proxy_value(anchor, array_index);
|
||||||
++anchor;
|
++anchor;
|
||||||
@@ -122,7 +122,7 @@ template<typename IteratorType> class iteration_proxy_value
|
|||||||
{
|
{
|
||||||
if (array_index != array_index_last)
|
if (array_index != array_index_last)
|
||||||
{
|
{
|
||||||
int_to_string( array_index_str, array_index );
|
int_to_string(array_index_str, array_index);
|
||||||
array_index_last = array_index;
|
array_index_last = array_index;
|
||||||
}
|
}
|
||||||
return array_index_str;
|
return array_index_str;
|
||||||
@@ -154,7 +154,8 @@ template<typename IteratorType> class iteration_proxy_value
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// proxy class for the items() function
|
/// proxy class for the items() function
|
||||||
template<typename IteratorType> class iteration_proxy
|
template<typename IteratorType>
|
||||||
|
class iteration_proxy
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
/// the container to iterate
|
/// the container to iterate
|
||||||
@@ -165,7 +166,8 @@ template<typename IteratorType> class iteration_proxy
|
|||||||
|
|
||||||
/// construct iteration proxy from a container
|
/// construct iteration proxy from a container
|
||||||
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
|
explicit iteration_proxy(typename IteratorType::reference cont) noexcept
|
||||||
: container(&cont) {}
|
: container(&cont)
|
||||||
|
{}
|
||||||
|
|
||||||
iteration_proxy(iteration_proxy const&) = default;
|
iteration_proxy(iteration_proxy const&) = default;
|
||||||
iteration_proxy& operator=(iteration_proxy const&) = default;
|
iteration_proxy& operator=(iteration_proxy const&) = default;
|
||||||
@@ -219,16 +221,15 @@ namespace std
|
|||||||
#pragma clang diagnostic ignored "-Wmismatched-tags"
|
#pragma clang diagnostic ignored "-Wmismatched-tags"
|
||||||
#endif
|
#endif
|
||||||
template<typename IteratorType>
|
template<typename IteratorType>
|
||||||
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
|
class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
|
||||||
: public std::integral_constant<std::size_t, 2> {};
|
: public std::integral_constant<std::size_t, 2>
|
||||||
|
{};
|
||||||
|
|
||||||
template<std::size_t N, typename IteratorType>
|
template<std::size_t N, typename IteratorType>
|
||||||
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
|
class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using type = decltype(
|
using type = decltype(get<N>(std::declval<::nlohmann::detail::iteration_proxy_value<IteratorType>>()));
|
||||||
get<N>(std::declval <
|
|
||||||
::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
|
|
||||||
};
|
};
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#pragma clang diagnostic pop
|
#pragma clang diagnostic pop
|
||||||
@@ -237,6 +238,6 @@ class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >>
|
|||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#if JSON_HAS_RANGES
|
#if JSON_HAS_RANGES
|
||||||
template <typename IteratorType>
|
template<typename IteratorType>
|
||||||
inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
|
inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -8,24 +8,24 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <iterator> // random_access_iterator_tag
|
#include <iterator> // random_access_iterator_tag
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/meta/void_t.hpp>
|
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
|
#include <nlohmann/detail/meta/void_t.hpp>
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename It, typename = void>
|
template<typename It, typename = void>
|
||||||
struct iterator_types {};
|
struct iterator_types
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename It>
|
template<typename It>
|
||||||
struct iterator_types <
|
struct iterator_types<
|
||||||
It,
|
It,
|
||||||
void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
|
void_t<typename It::difference_type, typename It::value_type, typename It::pointer, typename It::reference, typename It::iterator_category>>
|
||||||
typename It::reference, typename It::iterator_category >>
|
|
||||||
{
|
{
|
||||||
using difference_type = typename It::difference_type;
|
using difference_type = typename It::difference_type;
|
||||||
using value_type = typename It::value_type;
|
using value_type = typename It::value_type;
|
||||||
@@ -38,14 +38,11 @@ struct iterator_types <
|
|||||||
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
|
// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
|
||||||
template<typename T, typename = void>
|
template<typename T, typename = void>
|
||||||
struct iterator_traits
|
struct iterator_traits
|
||||||
{
|
{};
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
|
struct iterator_traits<T, enable_if_t<!std::is_pointer<T>::value>> : iterator_types<T>
|
||||||
: iterator_types<T>
|
{};
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
|
struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // ptrdiff_t
|
#include <cstddef> // ptrdiff_t
|
||||||
#include <iterator> // reverse_iterator
|
#include <iterator> // reverse_iterator
|
||||||
#include <utility> // declval
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
@@ -52,13 +52,16 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
|
|||||||
|
|
||||||
/// create reverse iterator from iterator
|
/// create reverse iterator from iterator
|
||||||
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
|
explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
|
||||||
: base_iterator(it) {}
|
: base_iterator(it)
|
||||||
|
{}
|
||||||
|
|
||||||
/// create reverse iterator from base class
|
/// create reverse iterator from base class
|
||||||
explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
|
explicit json_reverse_iterator(const base_iterator& it) noexcept
|
||||||
|
: base_iterator(it)
|
||||||
|
{}
|
||||||
|
|
||||||
/// post-increment (it++)
|
/// post-increment (it++)
|
||||||
json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
|
json_reverse_iterator operator++(int) & // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
|
return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
|
||||||
}
|
}
|
||||||
@@ -70,7 +73,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// post-decrement (it--)
|
/// post-decrement (it--)
|
||||||
json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
|
json_reverse_iterator operator--(int) & // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
|
return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
|
||||||
}
|
}
|
||||||
@@ -122,7 +125,7 @@ class json_reverse_iterator : public std::reverse_iterator<Base>
|
|||||||
reference value() const
|
reference value() const
|
||||||
{
|
{
|
||||||
auto it = --this->base();
|
auto it = --this->base();
|
||||||
return it.operator * ();
|
return it.operator*();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstddef> // ptrdiff_t
|
#include <cstddef> // ptrdiff_t
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class primitive_iterator_t
|
|||||||
static constexpr difference_type begin_value = 0;
|
static constexpr difference_type begin_value = 0;
|
||||||
static constexpr difference_type end_value = begin_value + 1;
|
static constexpr difference_type end_value = begin_value + 1;
|
||||||
|
|
||||||
JSON_PRIVATE_UNLESS_TESTED:
|
JSON_PRIVATE_UNLESS_TESTED :
|
||||||
/// iterator as signed integer type
|
/// iterator as signed integer type
|
||||||
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
|
difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ class primitive_iterator_t
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
|
primitive_iterator_t operator++(int) & noexcept // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
auto result = *this;
|
auto result = *this;
|
||||||
++m_it;
|
++m_it;
|
||||||
@@ -108,7 +108,7 @@ class primitive_iterator_t
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
|
primitive_iterator_t operator--(int) & noexcept // NOLINT(cert-dcl21-cpp)
|
||||||
{
|
{
|
||||||
auto result = *this;
|
auto result = *this;
|
||||||
--m_it;
|
--m_it;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <type_traits> // conditional, is_same
|
#include <type_traits> // conditional, is_same
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
@@ -26,14 +26,11 @@ of @ref basic_json do not require complex case distinctions
|
|||||||
By default, this class is used because it is empty and thus has no effect
|
By default, this class is used because it is empty and thus has no effect
|
||||||
on the behavior of @ref basic_json.
|
on the behavior of @ref basic_json.
|
||||||
*/
|
*/
|
||||||
struct json_default_base {};
|
struct json_default_base
|
||||||
|
{};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
using json_base_class = typename std::conditional <
|
using json_base_class = typename std::conditional<std::is_same<T, void>::value, json_default_base, T>::type;
|
||||||
std::is_same<T, void>::value,
|
|
||||||
json_default_base,
|
|
||||||
T
|
|
||||||
>::type;
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|||||||
@@ -8,18 +8,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // all_of
|
#include <algorithm> // all_of
|
||||||
#include <cctype> // isdigit
|
#include <cctype> // isdigit
|
||||||
#include <cerrno> // errno, ERANGE
|
#include <cerrno> // errno, ERANGE
|
||||||
#include <cstdlib> // strtoull
|
#include <cstdlib> // strtoull
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
#include <iosfwd> // ostream
|
#include <iosfwd> // ostream
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
#include <limits> // max
|
#include <limits> // max
|
||||||
#include <numeric> // accumulate
|
#include <numeric> // accumulate
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -60,17 +60,14 @@ class json_pointer
|
|||||||
/// @brief create JSON pointer
|
/// @brief create JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
|
/// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
|
||||||
explicit json_pointer(const string_t& s = "")
|
explicit json_pointer(const string_t& s = "")
|
||||||
: reference_tokens(split(s))
|
: reference_tokens(split(s))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/// @brief return a string representation of the JSON pointer
|
/// @brief return a string representation of the JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
|
/// @sa https://json.nlohmann.me/api/json_pointer/to_string/
|
||||||
string_t to_string() const
|
string_t to_string() const
|
||||||
{
|
{
|
||||||
return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
|
return std::accumulate(reference_tokens.begin(), reference_tokens.end(), string_t{}, [](const string_t& a, const string_t& b) {
|
||||||
string_t{},
|
|
||||||
[](const string_t& a, const string_t& b)
|
|
||||||
{
|
|
||||||
return detail::concat(a, '/', detail::escape(b));
|
return detail::concat(a, '/', detail::escape(b));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -97,9 +94,7 @@ class json_pointer
|
|||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
|
||||||
json_pointer& operator/=(const json_pointer& ptr)
|
json_pointer& operator/=(const json_pointer& ptr)
|
||||||
{
|
{
|
||||||
reference_tokens.insert(reference_tokens.end(),
|
reference_tokens.insert(reference_tokens.end(), ptr.reference_tokens.begin(), ptr.reference_tokens.end());
|
||||||
ptr.reference_tokens.begin(),
|
|
||||||
ptr.reference_tokens.end());
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -120,15 +115,14 @@ class json_pointer
|
|||||||
|
|
||||||
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
/// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
|
||||||
friend json_pointer operator/(const json_pointer& lhs,
|
friend json_pointer operator/(const json_pointer& lhs, const json_pointer& rhs)
|
||||||
const json_pointer& rhs)
|
|
||||||
{
|
{
|
||||||
return json_pointer(lhs) /= rhs;
|
return json_pointer(lhs) /= rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
|
/// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
|
||||||
friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
|
friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
|
||||||
{
|
{
|
||||||
return json_pointer(lhs) /= std::move(token);
|
return json_pointer(lhs) /= std::move(token);
|
||||||
}
|
}
|
||||||
@@ -229,11 +223,11 @@ class json_pointer
|
|||||||
|
|
||||||
const char* p = s.c_str();
|
const char* p = s.c_str();
|
||||||
char* p_end = nullptr;
|
char* p_end = nullptr;
|
||||||
errno = 0; // strtoull doesn't reset errno
|
errno = 0; // strtoull doesn't reset errno
|
||||||
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
|
const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
|
||||||
if (p == p_end // invalid input or empty string
|
if (p == p_end // invalid input or empty string
|
||||||
|| errno == ERANGE // out of range
|
|| errno == ERANGE // out of range
|
||||||
|| JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
|
|| JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
|
JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
|
||||||
}
|
}
|
||||||
@@ -242,13 +236,13 @@ class json_pointer
|
|||||||
// https://github.com/nlohmann/json/pull/2203
|
// https://github.com/nlohmann/json/pull/2203
|
||||||
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
|
if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
|
JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<size_type>(res);
|
return static_cast<size_type>(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_PRIVATE_UNLESS_TESTED:
|
JSON_PRIVATE_UNLESS_TESTED :
|
||||||
json_pointer top() const
|
json_pointer top() const
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(empty()))
|
if (JSON_HEDLEY_UNLIKELY(empty()))
|
||||||
@@ -257,7 +251,7 @@ class json_pointer
|
|||||||
}
|
}
|
||||||
|
|
||||||
json_pointer result = *this;
|
json_pointer result = *this;
|
||||||
result.reference_tokens = {reference_tokens[0]};
|
result.reference_tokens = { reference_tokens[0] };
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -359,17 +353,12 @@ class json_pointer
|
|||||||
if (ptr->is_null())
|
if (ptr->is_null())
|
||||||
{
|
{
|
||||||
// check if reference token is a number
|
// check if reference token is a number
|
||||||
const bool nums =
|
const bool nums = std::all_of(reference_token.begin(), reference_token.end(), [](const unsigned char x) {
|
||||||
std::all_of(reference_token.begin(), reference_token.end(),
|
|
||||||
[](const unsigned char x)
|
|
||||||
{
|
|
||||||
return std::isdigit(x);
|
return std::isdigit(x);
|
||||||
});
|
});
|
||||||
|
|
||||||
// change value to array for numbers or "-" or to object otherwise
|
// change value to array for numbers or "-" or to object otherwise
|
||||||
*ptr = (nums || reference_token == "-")
|
*ptr = (nums || reference_token == "-") ? detail::value_t::array : detail::value_t::object;
|
||||||
? detail::value_t::array
|
|
||||||
: detail::value_t::object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (ptr->type())
|
switch (ptr->type())
|
||||||
@@ -437,9 +426,10 @@ class json_pointer
|
|||||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||||
{
|
{
|
||||||
// "-" always fails the range check
|
// "-" always fails the range check
|
||||||
JSON_THROW(detail::out_of_range::create(402, detail::concat(
|
JSON_THROW(detail::out_of_range::create(
|
||||||
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
|
402,
|
||||||
") is out of range"), ptr));
|
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
|
||||||
|
ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: at performs range check
|
// note: at performs range check
|
||||||
@@ -495,7 +485,10 @@ class json_pointer
|
|||||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||||
{
|
{
|
||||||
// "-" cannot be used for const access
|
// "-" cannot be used for const access
|
||||||
JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
|
JSON_THROW(detail::out_of_range::create(
|
||||||
|
402,
|
||||||
|
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
|
||||||
|
ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// use unchecked array access
|
// use unchecked array access
|
||||||
@@ -544,9 +537,10 @@ class json_pointer
|
|||||||
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
|
||||||
{
|
{
|
||||||
// "-" always fails the range check
|
// "-" always fails the range check
|
||||||
JSON_THROW(detail::out_of_range::create(402, detail::concat(
|
JSON_THROW(detail::out_of_range::create(
|
||||||
"array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
|
402,
|
||||||
") is out of range"), ptr));
|
detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"),
|
||||||
|
ptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// note: at performs range check
|
// note: at performs range check
|
||||||
@@ -676,7 +670,8 @@ class json_pointer
|
|||||||
// check if nonempty reference string begins with slash
|
// check if nonempty reference string begins with slash
|
||||||
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
|
if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
|
JSON_THROW(
|
||||||
|
detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
// extract the reference tokens:
|
// extract the reference tokens:
|
||||||
@@ -685,14 +680,14 @@ class json_pointer
|
|||||||
for (
|
for (
|
||||||
// search for the first slash after the first character
|
// search for the first slash after the first character
|
||||||
std::size_t slash = reference_string.find_first_of('/', 1),
|
std::size_t slash = reference_string.find_first_of('/', 1),
|
||||||
// set the beginning of the first reference token
|
// set the beginning of the first reference token
|
||||||
start = 1;
|
start = 1;
|
||||||
// we can stop if start == 0 (if slash == string_t::npos)
|
// we can stop if start == 0 (if slash == string_t::npos)
|
||||||
start != 0;
|
start != 0;
|
||||||
// set the beginning of the next reference token
|
// set the beginning of the next reference token
|
||||||
// (will eventually be 0 if slash == string_t::npos)
|
// (will eventually be 0 if slash == string_t::npos)
|
||||||
start = (slash == string_t::npos) ? 0 : slash + 1,
|
start = (slash == string_t::npos) ? 0 : slash + 1,
|
||||||
// find next slash
|
// find next slash
|
||||||
slash = reference_string.find_first_of('/', start))
|
slash = reference_string.find_first_of('/', start))
|
||||||
{
|
{
|
||||||
// use the text between the beginning of the reference token
|
// use the text between the beginning of the reference token
|
||||||
@@ -700,16 +695,12 @@ class json_pointer
|
|||||||
auto reference_token = reference_string.substr(start, slash - start);
|
auto reference_token = reference_string.substr(start, slash - start);
|
||||||
|
|
||||||
// check reference tokens are properly escaped
|
// check reference tokens are properly escaped
|
||||||
for (std::size_t pos = reference_token.find_first_of('~');
|
for (std::size_t pos = reference_token.find_first_of('~'); pos != string_t::npos; pos = reference_token.find_first_of('~', pos + 1))
|
||||||
pos != string_t::npos;
|
|
||||||
pos = reference_token.find_first_of('~', pos + 1))
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(reference_token[pos] == '~');
|
JSON_ASSERT(reference_token[pos] == '~');
|
||||||
|
|
||||||
// ~ must be followed by 0 or 1
|
// ~ must be followed by 0 or 1
|
||||||
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
|
if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 || (reference_token[pos + 1] != '0' && reference_token[pos + 1] != '1')))
|
||||||
(reference_token[pos + 1] != '0' &&
|
|
||||||
reference_token[pos + 1] != '1')))
|
|
||||||
{
|
{
|
||||||
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
|
JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
|
||||||
}
|
}
|
||||||
@@ -732,9 +723,7 @@ class json_pointer
|
|||||||
@note Empty objects or arrays are flattened to `null`.
|
@note Empty objects or arrays are flattened to `null`.
|
||||||
*/
|
*/
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static void flatten(const string_t& reference_string,
|
static void flatten(const string_t& reference_string, const BasicJsonType& value, BasicJsonType& result)
|
||||||
const BasicJsonType& value,
|
|
||||||
BasicJsonType& result)
|
|
||||||
{
|
{
|
||||||
switch (value.type())
|
switch (value.type())
|
||||||
{
|
{
|
||||||
@@ -750,8 +739,7 @@ class json_pointer
|
|||||||
// iterate array and use index as reference string
|
// iterate array and use index as reference string
|
||||||
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
|
for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
|
||||||
{
|
{
|
||||||
flatten(detail::concat(reference_string, '/', std::to_string(i)),
|
flatten(detail::concat(reference_string, '/', std::to_string(i)), value.m_data.m_value.array->operator[](i), result);
|
||||||
value.m_data.m_value.array->operator[](i), result);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -803,8 +791,7 @@ class json_pointer
|
|||||||
@throw type_error.313 if value cannot be unflattened
|
@throw type_error.313 if value cannot be unflattened
|
||||||
*/
|
*/
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
static BasicJsonType
|
static BasicJsonType unflatten(const BasicJsonType& value)
|
||||||
unflatten(const BasicJsonType& value)
|
|
||||||
{
|
{
|
||||||
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
|
||||||
{
|
{
|
||||||
@@ -839,7 +826,7 @@ class json_pointer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
json_pointer<string_t> convert()&&
|
json_pointer<string_t> convert() &&
|
||||||
{
|
{
|
||||||
json_pointer<string_t> result;
|
json_pointer<string_t> result;
|
||||||
result.reference_tokens = std::move(reference_tokens);
|
result.reference_tokens = std::move(reference_tokens);
|
||||||
@@ -866,58 +853,51 @@ class json_pointer
|
|||||||
|
|
||||||
/// @brief 3-way compares two JSON pointers
|
/// @brief 3-way compares two JSON pointers
|
||||||
template<typename RefStringTypeRhs>
|
template<typename RefStringTypeRhs>
|
||||||
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
|
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
|
||||||
{
|
{
|
||||||
return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
|
return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
/// @brief compares two JSON pointers for equality
|
/// @brief compares two JSON pointers for equality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
|
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
|
||||||
|
|
||||||
/// @brief compares JSON pointer and string for equality
|
/// @brief compares JSON pointer and string for equality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
||||||
template<typename RefStringTypeLhs, typename StringType>
|
template<typename RefStringTypeLhs, typename StringType>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
|
friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
|
||||||
const StringType& rhs);
|
|
||||||
|
|
||||||
/// @brief compares string and JSON pointer for equality
|
/// @brief compares string and JSON pointer for equality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
|
||||||
template<typename RefStringTypeRhs, typename StringType>
|
template<typename RefStringTypeRhs, typename StringType>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator==(const StringType& lhs,
|
friend bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
|
||||||
const json_pointer<RefStringTypeRhs>& rhs);
|
|
||||||
|
|
||||||
/// @brief compares two JSON pointers for inequality
|
/// @brief compares two JSON pointers for inequality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
|
||||||
|
|
||||||
/// @brief compares JSON pointer and string for inequality
|
/// @brief compares JSON pointer and string for inequality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
||||||
template<typename RefStringTypeLhs, typename StringType>
|
template<typename RefStringTypeLhs, typename StringType>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs);
|
||||||
const StringType& rhs);
|
|
||||||
|
|
||||||
/// @brief compares string and JSON pointer for inequality
|
/// @brief compares string and JSON pointer for inequality
|
||||||
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
/// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
|
||||||
template<typename RefStringTypeRhs, typename StringType>
|
template<typename RefStringTypeRhs, typename StringType>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator!=(const StringType& lhs,
|
friend bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs);
|
||||||
const json_pointer<RefStringTypeRhs>& rhs);
|
|
||||||
|
|
||||||
/// @brief compares two JSON pointer for less-than
|
/// @brief compares two JSON pointer for less-than
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
// NOLINTNEXTLINE(readability-redundant-declaration)
|
// NOLINTNEXTLINE(readability-redundant-declaration)
|
||||||
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
|
friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -928,58 +908,47 @@ class json_pointer
|
|||||||
#if !JSON_HAS_THREE_WAY_COMPARISON
|
#if !JSON_HAS_THREE_WAY_COMPARISON
|
||||||
// functions cannot be defined inside class due to ODR violations
|
// functions cannot be defined inside class due to ODR violations
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
|
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
|
||||||
{
|
{
|
||||||
return lhs.reference_tokens == rhs.reference_tokens;
|
return lhs.reference_tokens == rhs.reference_tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeLhs,
|
template<typename RefStringTypeLhs, typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
|
||||||
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
||||||
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
|
inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs)
|
||||||
const StringType& rhs)
|
|
||||||
{
|
{
|
||||||
return lhs == json_pointer<RefStringTypeLhs>(rhs);
|
return lhs == json_pointer<RefStringTypeLhs>(rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeRhs,
|
template<typename RefStringTypeRhs, typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
||||||
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
|
||||||
inline bool operator==(const StringType& lhs,
|
inline bool operator==(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs)
|
||||||
const json_pointer<RefStringTypeRhs>& rhs)
|
|
||||||
{
|
{
|
||||||
return json_pointer<RefStringTypeRhs>(lhs) == rhs;
|
return json_pointer<RefStringTypeRhs>(lhs) == rhs;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeLhs,
|
template<typename RefStringTypeLhs, typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
|
||||||
typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
||||||
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
|
inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs, const StringType& rhs)
|
||||||
const StringType& rhs)
|
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeRhs,
|
template<typename RefStringTypeRhs, typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
||||||
typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
|
|
||||||
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
|
||||||
inline bool operator!=(const StringType& lhs,
|
inline bool operator!=(const StringType& lhs, const json_pointer<RefStringTypeRhs>& rhs)
|
||||||
const json_pointer<RefStringTypeRhs>& rhs)
|
|
||||||
{
|
{
|
||||||
return !(lhs == rhs);
|
return !(lhs == rhs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
template<typename RefStringTypeLhs, typename RefStringTypeRhs>
|
||||||
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
|
inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs, const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
||||||
const json_pointer<RefStringTypeRhs>& rhs) noexcept
|
|
||||||
{
|
{
|
||||||
return lhs.reference_tokens < rhs.reference_tokens;
|
return lhs.reference_tokens < rhs.reference_tokens;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,22 +25,20 @@ class json_ref
|
|||||||
using value_type = BasicJsonType;
|
using value_type = BasicJsonType;
|
||||||
|
|
||||||
json_ref(value_type&& value)
|
json_ref(value_type&& value)
|
||||||
: owned_value(std::move(value))
|
: owned_value(std::move(value))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json_ref(const value_type& value)
|
json_ref(const value_type& value)
|
||||||
: value_ref(&value)
|
: value_ref(&value)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
json_ref(std::initializer_list<json_ref> init)
|
json_ref(std::initializer_list<json_ref> init)
|
||||||
: owned_value(init)
|
: owned_value(init)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
template <
|
template<class... Args, enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0>
|
||||||
class... Args,
|
json_ref(Args&&... args)
|
||||||
enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
|
: owned_value(std::forward<Args>(args)...)
|
||||||
json_ref(Args && ... args)
|
|
||||||
: owned_value(std::forward<Args>(args)...)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// class should be movable only
|
// class should be movable only
|
||||||
@@ -66,7 +64,7 @@ class json_ref
|
|||||||
|
|
||||||
value_type const* operator->() const
|
value_type const* operator->() const
|
||||||
{
|
{
|
||||||
return &** this;
|
return &**this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
+3659
-215
File diff suppressed because it is too large
Load Diff
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
|
||||||
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
|
#include <utility> // index_sequence, make_index_sequence, index_sequence_for
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
@@ -28,8 +28,8 @@ using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::typ
|
|||||||
// the following utilities are natively available in C++14
|
// the following utilities are natively available in C++14
|
||||||
using std::enable_if_t;
|
using std::enable_if_t;
|
||||||
using std::index_sequence;
|
using std::index_sequence;
|
||||||
using std::make_index_sequence;
|
|
||||||
using std::index_sequence_for;
|
using std::index_sequence_for;
|
||||||
|
using std::make_index_sequence;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ using enable_if_t = typename std::enable_if<B, T>::type;
|
|||||||
// // will be deduced to `0, 1, 2, 3, 4`.
|
// // will be deduced to `0, 1, 2, 3, 4`.
|
||||||
// user_function(make_integer_sequence<int, 5>());
|
// user_function(make_integer_sequence<int, 5>());
|
||||||
// }
|
// }
|
||||||
template <typename T, T... Ints>
|
template<typename T, T... Ints>
|
||||||
struct integer_sequence
|
struct integer_sequence
|
||||||
{
|
{
|
||||||
using value_type = T;
|
using value_type = T;
|
||||||
@@ -76,38 +76,37 @@ struct integer_sequence
|
|||||||
// A helper template for an `integer_sequence` of `size_t`,
|
// A helper template for an `integer_sequence` of `size_t`,
|
||||||
// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
|
// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
|
||||||
// `std::index_sequence`.
|
// `std::index_sequence`.
|
||||||
template <size_t... Ints>
|
template<size_t... Ints>
|
||||||
using index_sequence = integer_sequence<size_t, Ints...>;
|
using index_sequence = integer_sequence<size_t, Ints...>;
|
||||||
|
|
||||||
namespace utility_internal
|
namespace utility_internal
|
||||||
{
|
{
|
||||||
|
|
||||||
template <typename Seq, size_t SeqSize, size_t Rem>
|
template<typename Seq, size_t SeqSize, size_t Rem>
|
||||||
struct Extend;
|
struct Extend;
|
||||||
|
|
||||||
// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
|
// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
|
||||||
template <typename T, T... Ints, size_t SeqSize>
|
template<typename T, T... Ints, size_t SeqSize>
|
||||||
struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
|
struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
|
||||||
{
|
{
|
||||||
using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
|
using type = integer_sequence<T, Ints..., (Ints + SeqSize)...>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, T... Ints, size_t SeqSize>
|
template<typename T, T... Ints, size_t SeqSize>
|
||||||
struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
|
struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
|
||||||
{
|
{
|
||||||
using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
|
using type = integer_sequence<T, Ints..., (Ints + SeqSize)..., 2 * SeqSize>;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Recursion helper for 'make_integer_sequence<T, N>'.
|
// Recursion helper for 'make_integer_sequence<T, N>'.
|
||||||
// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
|
// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
|
||||||
template <typename T, size_t N>
|
template<typename T, size_t N>
|
||||||
struct Gen
|
struct Gen
|
||||||
{
|
{
|
||||||
using type =
|
using type = typename Extend<typename Gen<T, N / 2>::type, N / 2, N % 2>::type;
|
||||||
typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct Gen<T, 0>
|
struct Gen<T, 0>
|
||||||
{
|
{
|
||||||
using type = integer_sequence<T>;
|
using type = integer_sequence<T>;
|
||||||
@@ -122,7 +121,7 @@ struct Gen<T, 0>
|
|||||||
// This template alias is equivalent to
|
// This template alias is equivalent to
|
||||||
// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
|
// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
|
||||||
// replacement for C++14's `std::make_integer_sequence`.
|
// replacement for C++14's `std::make_integer_sequence`.
|
||||||
template <typename T, T N>
|
template<typename T, T N>
|
||||||
using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
|
using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
|
||||||
|
|
||||||
// make_index_sequence
|
// make_index_sequence
|
||||||
@@ -130,7 +129,7 @@ using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
|
|||||||
// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
|
// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
|
||||||
// and is designed to be a drop-in replacement for C++14's
|
// and is designed to be a drop-in replacement for C++14's
|
||||||
// `std::make_index_sequence`.
|
// `std::make_index_sequence`.
|
||||||
template <size_t N>
|
template<size_t N>
|
||||||
using make_index_sequence = make_integer_sequence<size_t, N>;
|
using make_index_sequence = make_integer_sequence<size_t, N>;
|
||||||
|
|
||||||
// index_sequence_for
|
// index_sequence_for
|
||||||
@@ -138,7 +137,7 @@ using make_index_sequence = make_integer_sequence<size_t, N>;
|
|||||||
// Converts a typename pack into an index sequence of the same length, and
|
// Converts a typename pack into an index sequence of the same length, and
|
||||||
// is designed to be a drop-in replacement for C++14's
|
// is designed to be a drop-in replacement for C++14's
|
||||||
// `std::index_sequence_for()`
|
// `std::index_sequence_for()`
|
||||||
template <typename... Ts>
|
template<typename... Ts>
|
||||||
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
||||||
|
|
||||||
//// END OF CODE FROM GOOGLE ABSEIL
|
//// END OF CODE FROM GOOGLE ABSEIL
|
||||||
@@ -146,8 +145,12 @@ using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// dispatch utility (taken from ranges-v3)
|
// dispatch utility (taken from ranges-v3)
|
||||||
template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
|
template<unsigned N>
|
||||||
template<> struct priority_tag<0> {};
|
struct priority_tag : priority_tag<N - 1>
|
||||||
|
{};
|
||||||
|
template<>
|
||||||
|
struct priority_tag<0>
|
||||||
|
{};
|
||||||
|
|
||||||
// taken from ranges-v3
|
// taken from ranges-v3
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -157,14 +160,14 @@ struct static_const
|
|||||||
};
|
};
|
||||||
|
|
||||||
#ifndef JSON_HAS_CPP_17
|
#ifndef JSON_HAS_CPP_17
|
||||||
template<typename T>
|
template<typename T>
|
||||||
constexpr T static_const<T>::value;
|
constexpr T static_const<T>::value;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
|
inline constexpr std::array<T, sizeof...(Args)> make_array(Args&&... args)
|
||||||
{
|
{
|
||||||
return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
|
return std::array<T, sizeof...(Args)>{ { static_cast<T>(std::forward<Args>(args))... } };
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -27,10 +27,7 @@ struct nonesuch
|
|||||||
void operator=(nonesuch&&) = delete;
|
void operator=(nonesuch&&) = delete;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Default,
|
template<class Default, class AlwaysVoid, template<class...> class Op, class... Args>
|
||||||
class AlwaysVoid,
|
|
||||||
template<class...> class Op,
|
|
||||||
class... Args>
|
|
||||||
struct detector
|
struct detector
|
||||||
{
|
{
|
||||||
using value_t = std::false_type;
|
using value_t = std::false_type;
|
||||||
@@ -48,7 +45,8 @@ template<template<class...> class Op, class... Args>
|
|||||||
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
|
using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
|
||||||
|
|
||||||
template<template<class...> class Op, class... Args>
|
template<template<class...> class Op, class... Args>
|
||||||
struct is_detected_lazy : is_detected<Op, Args...> { };
|
struct is_detected_lazy : is_detected<Op, Args...>
|
||||||
|
{};
|
||||||
|
|
||||||
template<template<class...> class Op, class... Args>
|
template<template<class...> class Op, class... Args>
|
||||||
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
|
using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
|
||||||
@@ -63,8 +61,7 @@ template<class Expected, template<class...> class Op, class... Args>
|
|||||||
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
|
using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
|
||||||
|
|
||||||
template<class To, template<class...> class Op, class... Args>
|
template<class To, template<class...> class Op, class... Args>
|
||||||
using is_detected_convertible =
|
using is_detected_convertible = std::is_convertible<detected_t<Op, Args...>, To>;
|
||||||
std::is_convertible<detected_t<Op, Args...>, To>;
|
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
// dispatching helper struct
|
// dispatching helper struct
|
||||||
template <class T> struct identity_tag {};
|
template<class T>
|
||||||
|
struct identity_tag
|
||||||
|
{};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // size_t
|
#include <cstdint> // size_t
|
||||||
#include <utility> // declval
|
#include <string> // string
|
||||||
#include <string> // string
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
#include <nlohmann/detail/meta/detected.hpp>
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
@@ -24,58 +24,47 @@ template<typename T>
|
|||||||
using null_function_t = decltype(std::declval<T&>().null());
|
using null_function_t = decltype(std::declval<T&>().null());
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using boolean_function_t =
|
using boolean_function_t = decltype(std::declval<T&>().boolean(std::declval<bool>()));
|
||||||
decltype(std::declval<T&>().boolean(std::declval<bool>()));
|
|
||||||
|
|
||||||
template<typename T, typename Integer>
|
template<typename T, typename Integer>
|
||||||
using number_integer_function_t =
|
using number_integer_function_t = decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
|
||||||
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
|
|
||||||
|
|
||||||
template<typename T, typename Unsigned>
|
template<typename T, typename Unsigned>
|
||||||
using number_unsigned_function_t =
|
using number_unsigned_function_t = decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
|
||||||
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
|
|
||||||
|
|
||||||
template<typename T, typename Float, typename String>
|
template<typename T, typename Float, typename String>
|
||||||
using number_float_function_t = decltype(std::declval<T&>().number_float(
|
using number_float_function_t = decltype(std::declval<T&>().number_float(std::declval<Float>(), std::declval<const String&>()));
|
||||||
std::declval<Float>(), std::declval<const String&>()));
|
|
||||||
|
|
||||||
template<typename T, typename String>
|
template<typename T, typename String>
|
||||||
using string_function_t =
|
using string_function_t = decltype(std::declval<T&>().string(std::declval<String&>()));
|
||||||
decltype(std::declval<T&>().string(std::declval<String&>()));
|
|
||||||
|
|
||||||
template<typename T, typename Binary>
|
template<typename T, typename Binary>
|
||||||
using binary_function_t =
|
using binary_function_t = decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
||||||
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using start_object_function_t =
|
using start_object_function_t = decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
||||||
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
|
||||||
|
|
||||||
template<typename T, typename String>
|
template<typename T, typename String>
|
||||||
using key_function_t =
|
using key_function_t = decltype(std::declval<T&>().key(std::declval<String&>()));
|
||||||
decltype(std::declval<T&>().key(std::declval<String&>()));
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using end_object_function_t = decltype(std::declval<T&>().end_object());
|
using end_object_function_t = decltype(std::declval<T&>().end_object());
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using start_array_function_t =
|
using start_array_function_t = decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
|
||||||
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
|
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using end_array_function_t = decltype(std::declval<T&>().end_array());
|
using end_array_function_t = decltype(std::declval<T&>().end_array());
|
||||||
|
|
||||||
template<typename T, typename Exception>
|
template<typename T, typename Exception>
|
||||||
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
|
using parse_error_function_t =
|
||||||
std::declval<std::size_t>(), std::declval<const std::string&>(),
|
decltype(std::declval<T&>().parse_error(std::declval<std::size_t>(), std::declval<const std::string&>(), std::declval<const Exception&>()));
|
||||||
std::declval<const Exception&>()));
|
|
||||||
|
|
||||||
template<typename SAX, typename BasicJsonType>
|
template<typename SAX, typename BasicJsonType>
|
||||||
struct is_sax
|
struct is_sax
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static_assert(is_basic_json<BasicJsonType>::value,
|
static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
|
||||||
"BasicJsonType must be of type basic_json<...>");
|
|
||||||
|
|
||||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
@@ -86,27 +75,21 @@ struct is_sax
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool value =
|
static constexpr bool value =
|
||||||
is_detected_exact<bool, null_function_t, SAX>::value &&
|
is_detected_exact<bool, null_function_t, SAX>::value && is_detected_exact<bool, boolean_function_t, SAX>::value &&
|
||||||
is_detected_exact<bool, boolean_function_t, SAX>::value &&
|
|
||||||
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
|
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
|
||||||
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
|
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
|
||||||
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
|
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
|
||||||
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
|
is_detected_exact<bool, string_function_t, SAX, string_t>::value && is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
|
||||||
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
|
is_detected_exact<bool, start_object_function_t, SAX>::value && is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
|
||||||
is_detected_exact<bool, start_object_function_t, SAX>::value &&
|
is_detected_exact<bool, end_object_function_t, SAX>::value && is_detected_exact<bool, start_array_function_t, SAX>::value &&
|
||||||
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
|
is_detected_exact<bool, end_array_function_t, SAX>::value && is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
|
||||||
is_detected_exact<bool, end_object_function_t, SAX>::value &&
|
|
||||||
is_detected_exact<bool, start_array_function_t, SAX>::value &&
|
|
||||||
is_detected_exact<bool, end_array_function_t, SAX>::value &&
|
|
||||||
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename SAX, typename BasicJsonType>
|
template<typename SAX, typename BasicJsonType>
|
||||||
struct is_sax_static_asserts
|
struct is_sax_static_asserts
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
static_assert(is_basic_json<BasicJsonType>::value,
|
static_assert(is_basic_json<BasicJsonType>::value, "BasicJsonType must be of type basic_json<...>");
|
||||||
"BasicJsonType must be of type basic_json<...>");
|
|
||||||
|
|
||||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||||
@@ -116,43 +99,25 @@ struct is_sax_static_asserts
|
|||||||
using exception_t = typename BasicJsonType::exception;
|
using exception_t = typename BasicJsonType::exception;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
|
static_assert(is_detected_exact<bool, null_function_t, SAX>::value, "Missing/invalid function: bool null()");
|
||||||
"Missing/invalid function: bool null()");
|
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, "Missing/invalid function: bool boolean(bool)");
|
||||||
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
|
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value, "Missing/invalid function: bool boolean(bool)");
|
||||||
"Missing/invalid function: bool boolean(bool)");
|
static_assert(is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value,
|
||||||
static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
|
"Missing/invalid function: bool number_integer(number_integer_t)");
|
||||||
"Missing/invalid function: bool boolean(bool)");
|
static_assert(is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value,
|
||||||
static_assert(
|
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
|
||||||
is_detected_exact<bool, number_integer_function_t, SAX,
|
static_assert(is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value,
|
||||||
number_integer_t>::value,
|
|
||||||
"Missing/invalid function: bool number_integer(number_integer_t)");
|
|
||||||
static_assert(
|
|
||||||
is_detected_exact<bool, number_unsigned_function_t, SAX,
|
|
||||||
number_unsigned_t>::value,
|
|
||||||
"Missing/invalid function: bool number_unsigned(number_unsigned_t)");
|
|
||||||
static_assert(is_detected_exact<bool, number_float_function_t, SAX,
|
|
||||||
number_float_t, string_t>::value,
|
|
||||||
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
|
"Missing/invalid function: bool number_float(number_float_t, const string_t&)");
|
||||||
static_assert(
|
static_assert(is_detected_exact<bool, string_function_t, SAX, string_t>::value, "Missing/invalid function: bool string(string_t&)");
|
||||||
is_detected_exact<bool, string_function_t, SAX, string_t>::value,
|
static_assert(is_detected_exact<bool, binary_function_t, SAX, binary_t>::value, "Missing/invalid function: bool binary(binary_t&)");
|
||||||
"Missing/invalid function: bool string(string_t&)");
|
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value, "Missing/invalid function: bool start_object(std::size_t)");
|
||||||
static_assert(
|
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value, "Missing/invalid function: bool key(string_t&)");
|
||||||
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
|
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value, "Missing/invalid function: bool end_object()");
|
||||||
"Missing/invalid function: bool binary(binary_t&)");
|
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value, "Missing/invalid function: bool start_array(std::size_t)");
|
||||||
static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
|
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value, "Missing/invalid function: bool end_array()");
|
||||||
"Missing/invalid function: bool start_object(std::size_t)");
|
static_assert(is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
|
||||||
static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
|
"Missing/invalid function: bool parse_error(std::size_t, const "
|
||||||
"Missing/invalid function: bool key(string_t&)");
|
"std::string&, const exception&)");
|
||||||
static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
|
|
||||||
"Missing/invalid function: bool end_object()");
|
|
||||||
static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
|
|
||||||
"Missing/invalid function: bool start_array(std::size_t)");
|
|
||||||
static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
|
|
||||||
"Missing/invalid function: bool end_array()");
|
|
||||||
static_assert(
|
|
||||||
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
|
|
||||||
"Missing/invalid function: bool parse_error(std::size_t, const "
|
|
||||||
"std::string&, const exception&)");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
|
||||||
#include <experimental/filesystem>
|
#include <experimental/filesystem>
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
@@ -19,7 +19,7 @@ namespace std_fs = std::experimental::filesystem;
|
|||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
#elif JSON_HAS_FILESYSTEM
|
#elif JSON_HAS_FILESYSTEM
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,11 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
#include <string> // char_traits
|
||||||
#include <utility> // declval
|
#include <tuple> // tuple
|
||||||
#include <tuple> // tuple
|
#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
|
||||||
#include <string> // char_traits
|
#include <utility> // declval
|
||||||
|
|
||||||
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
#include <nlohmann/detail/iterators/iterator_traits.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -47,19 +47,22 @@ namespace detail
|
|||||||
// In this case, T has to be properly CV-qualified to constraint the function arguments
|
// In this case, T has to be properly CV-qualified to constraint the function arguments
|
||||||
// (e.g. to_json(BasicJsonType&, const T&))
|
// (e.g. to_json(BasicJsonType&, const T&))
|
||||||
|
|
||||||
template<typename> struct is_basic_json : std::false_type {};
|
template<typename>
|
||||||
|
struct is_basic_json : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
NLOHMANN_BASIC_JSON_TPL_DECLARATION
|
||||||
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
|
struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
// used by exceptions create() member functions
|
// used by exceptions create() member functions
|
||||||
// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
|
// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
|
||||||
// false_type otherwise
|
// false_type otherwise
|
||||||
template<typename BasicJsonContext>
|
template<typename BasicJsonContext>
|
||||||
struct is_basic_json_context :
|
struct is_basic_json_context
|
||||||
std::integral_constant < bool,
|
: std::integral_constant<bool,
|
||||||
is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
|
is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value ||
|
||||||
|| std::is_same<BasicJsonContext, std::nullptr_t>::value >
|
std::is_same<BasicJsonContext, std::nullptr_t>::value>
|
||||||
{};
|
{};
|
||||||
|
|
||||||
//////////////////////
|
//////////////////////
|
||||||
@@ -70,10 +73,12 @@ template<typename>
|
|||||||
class json_ref;
|
class json_ref;
|
||||||
|
|
||||||
template<typename>
|
template<typename>
|
||||||
struct is_json_ref : std::false_type {};
|
struct is_json_ref : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_json_ref<json_ref<T>> : std::true_type {};
|
struct is_json_ref<json_ref<T>> : std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// aliases for detected //
|
// aliases for detected //
|
||||||
@@ -111,63 +116,61 @@ using get_template_function = decltype(std::declval<T>().template get<U>());
|
|||||||
|
|
||||||
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
|
||||||
template<typename BasicJsonType, typename T, typename = void>
|
template<typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_from_json : std::false_type {};
|
struct has_from_json : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
// trait checking if j.get<T> is valid
|
// trait checking if j.get<T> is valid
|
||||||
// use this trait instead of std::is_constructible or std::is_convertible,
|
// use this trait instead of std::is_constructible or std::is_convertible,
|
||||||
// both rely on, or make use of implicit conversions, and thus fail when T
|
// both rely on, or make use of implicit conversions, and thus fail when T
|
||||||
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
|
// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
|
||||||
template <typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct is_getable
|
struct is_getable
|
||||||
{
|
{
|
||||||
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
|
static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
struct has_from_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = is_detected_exact<void, from_json_function, serializer, const BasicJsonType&, T&>::value;
|
||||||
is_detected_exact<void, from_json_function, serializer,
|
|
||||||
const BasicJsonType&, T&>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
// This trait checks if JSONSerializer<T>::from_json(json const&) exists
|
||||||
// this overload is used for non-default-constructible user-defined-types
|
// this overload is used for non-default-constructible user-defined-types
|
||||||
template<typename BasicJsonType, typename T, typename = void>
|
template<typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_non_default_from_json : std::false_type {};
|
struct has_non_default_from_json : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
struct has_non_default_from_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = is_detected_exact<T, from_json_function, serializer, const BasicJsonType&>::value;
|
||||||
is_detected_exact<T, from_json_function, serializer,
|
|
||||||
const BasicJsonType&>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
|
||||||
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
|
// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
|
||||||
template<typename BasicJsonType, typename T, typename = void>
|
template<typename BasicJsonType, typename T, typename = void>
|
||||||
struct has_to_json : std::false_type {};
|
struct has_to_json : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
|
struct has_to_json<BasicJsonType, T, enable_if_t<!is_basic_json<T>::value>>
|
||||||
{
|
{
|
||||||
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
using serializer = typename BasicJsonType::template json_serializer<T, void>;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = is_detected_exact<void, to_json_function, serializer, BasicJsonType&, T>::value;
|
||||||
is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
|
|
||||||
T>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using detect_key_compare = typename T::key_compare;
|
using detect_key_compare = typename T::key_compare;
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
|
struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value>
|
||||||
|
{};
|
||||||
|
|
||||||
// obtains the actual object key comparator
|
// obtains the actual object key comparator
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
@@ -175,8 +178,7 @@ struct actual_object_comparator
|
|||||||
{
|
{
|
||||||
using object_t = typename BasicJsonType::object_t;
|
using object_t = typename BasicJsonType::object_t;
|
||||||
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
|
using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
|
||||||
using type = typename std::conditional < has_key_compare<object_t>::value,
|
using type = typename std::conditional<has_key_compare<object_t>::value, typename object_t::key_compare, object_comparator_t>::type;
|
||||||
typename object_t::key_compare, object_comparator_t>::type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
@@ -244,54 +246,67 @@ struct char_traits<signed char> : std::char_traits<char>
|
|||||||
///////////////////
|
///////////////////
|
||||||
|
|
||||||
// https://en.cppreference.com/w/cpp/types/conjunction
|
// https://en.cppreference.com/w/cpp/types/conjunction
|
||||||
template<class...> struct conjunction : std::true_type { };
|
template<class...>
|
||||||
template<class B> struct conjunction<B> : B { };
|
struct conjunction : std::true_type
|
||||||
|
{};
|
||||||
|
template<class B>
|
||||||
|
struct conjunction<B> : B
|
||||||
|
{};
|
||||||
template<class B, class... Bn>
|
template<class B, class... Bn>
|
||||||
struct conjunction<B, Bn...>
|
struct conjunction<B, Bn...> : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type
|
||||||
: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
|
{};
|
||||||
|
|
||||||
// https://en.cppreference.com/w/cpp/types/negation
|
// https://en.cppreference.com/w/cpp/types/negation
|
||||||
template<class B> struct negation : std::integral_constant < bool, !B::value > { };
|
template<class B>
|
||||||
|
struct negation : std::integral_constant<bool, !B::value>
|
||||||
|
{};
|
||||||
|
|
||||||
// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
|
// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
|
||||||
// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
|
// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
|
||||||
// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
|
// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct is_default_constructible : std::is_default_constructible<T> {};
|
struct is_default_constructible : std::is_default_constructible<T>
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct is_default_constructible<std::pair<T1, T2>>
|
struct is_default_constructible<std::pair<T1, T2>> : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
|
||||||
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
|
{};
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct is_default_constructible<const std::pair<T1, T2>>
|
struct is_default_constructible<const std::pair<T1, T2>> : conjunction<is_default_constructible<T1>, is_default_constructible<T2>>
|
||||||
: conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
|
{};
|
||||||
|
|
||||||
template <typename... Ts>
|
template<typename... Ts>
|
||||||
struct is_default_constructible<std::tuple<Ts...>>
|
struct is_default_constructible<std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
|
||||||
: conjunction<is_default_constructible<Ts>...> {};
|
{};
|
||||||
|
|
||||||
template <typename... Ts>
|
template<typename... Ts>
|
||||||
struct is_default_constructible<const std::tuple<Ts...>>
|
struct is_default_constructible<const std::tuple<Ts...>> : conjunction<is_default_constructible<Ts>...>
|
||||||
: conjunction<is_default_constructible<Ts>...> {};
|
{};
|
||||||
|
|
||||||
template <typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
struct is_constructible : std::is_constructible<T, Args...> {};
|
struct is_constructible : std::is_constructible<T, Args...>
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
|
struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>>
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
|
struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>>
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename... Ts>
|
template<typename... Ts>
|
||||||
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
|
struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>>
|
||||||
|
{};
|
||||||
|
|
||||||
template <typename... Ts>
|
template<typename... Ts>
|
||||||
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
|
struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>>
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T, typename = void>
|
template<typename T, typename = void>
|
||||||
struct is_iterator_traits : std::false_type {};
|
struct is_iterator_traits : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_iterator_traits<iterator_traits<T>>
|
struct is_iterator_traits<iterator_traits<T>>
|
||||||
@@ -300,12 +315,9 @@ struct is_iterator_traits<iterator_traits<T>>
|
|||||||
using traits = iterator_traits<T>;
|
using traits = iterator_traits<T>;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr auto value =
|
static constexpr auto value = is_detected<value_type_t, traits>::value && is_detected<difference_type_t, traits>::value &&
|
||||||
is_detected<value_type_t, traits>::value &&
|
is_detected<pointer_t, traits>::value && is_detected<iterator_category_t, traits>::value &&
|
||||||
is_detected<difference_type_t, traits>::value &&
|
is_detected<reference_t, traits>::value;
|
||||||
is_detected<pointer_t, traits>::value &&
|
|
||||||
is_detected<iterator_category_t, traits>::value &&
|
|
||||||
is_detected<reference_t, traits>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@@ -320,8 +332,7 @@ struct is_range
|
|||||||
// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
|
// to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
|
||||||
// and https://en.cppreference.com/w/cpp/iterator/sentinel_for
|
// and https://en.cppreference.com/w/cpp/iterator/sentinel_for
|
||||||
// but reimplementing these would be too much work, as a lot of other concepts are used underneath
|
// but reimplementing these would be too much work, as a lot of other concepts are used underneath
|
||||||
static constexpr auto is_iterator_begin =
|
static constexpr auto is_iterator_begin = is_iterator_traits<iterator_traits<iterator>>::value;
|
||||||
is_iterator_traits<iterator_traits<iterator>>::value;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
|
static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
|
||||||
@@ -338,73 +349,62 @@ using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
|
|||||||
// and is written by Xiang Fan who agreed to using it in this library.
|
// and is written by Xiang Fan who agreed to using it in this library.
|
||||||
|
|
||||||
template<typename T, typename = void>
|
template<typename T, typename = void>
|
||||||
struct is_complete_type : std::false_type {};
|
struct is_complete_type : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
|
struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleObjectType,
|
template<typename BasicJsonType, typename CompatibleObjectType, typename = void>
|
||||||
typename = void>
|
struct is_compatible_object_type_impl : std::false_type
|
||||||
struct is_compatible_object_type_impl : std::false_type {};
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleObjectType>
|
template<typename BasicJsonType, typename CompatibleObjectType>
|
||||||
struct is_compatible_object_type_impl <
|
struct is_compatible_object_type_impl<
|
||||||
BasicJsonType, CompatibleObjectType,
|
BasicJsonType,
|
||||||
enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
|
CompatibleObjectType,
|
||||||
is_detected<key_type_t, CompatibleObjectType>::value >>
|
enable_if_t<is_detected<mapped_type_t, CompatibleObjectType>::value && is_detected<key_type_t, CompatibleObjectType>::value>>
|
||||||
{
|
{
|
||||||
using object_t = typename BasicJsonType::object_t;
|
using object_t = typename BasicJsonType::object_t;
|
||||||
|
|
||||||
// macOS's is_constructible does not play well with nonesuch...
|
// macOS's is_constructible does not play well with nonesuch...
|
||||||
static constexpr bool value =
|
static constexpr bool value = is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value &&
|
||||||
is_constructible<typename object_t::key_type,
|
is_constructible<typename object_t::mapped_type, typename CompatibleObjectType::mapped_type>::value;
|
||||||
typename CompatibleObjectType::key_type>::value &&
|
|
||||||
is_constructible<typename object_t::mapped_type,
|
|
||||||
typename CompatibleObjectType::mapped_type>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleObjectType>
|
template<typename BasicJsonType, typename CompatibleObjectType>
|
||||||
struct is_compatible_object_type
|
struct is_compatible_object_type : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType>
|
||||||
: is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType,
|
template<typename BasicJsonType, typename ConstructibleObjectType, typename = void>
|
||||||
typename = void>
|
struct is_constructible_object_type_impl : std::false_type
|
||||||
struct is_constructible_object_type_impl : std::false_type {};
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType>
|
template<typename BasicJsonType, typename ConstructibleObjectType>
|
||||||
struct is_constructible_object_type_impl <
|
struct is_constructible_object_type_impl<
|
||||||
BasicJsonType, ConstructibleObjectType,
|
BasicJsonType,
|
||||||
enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
|
ConstructibleObjectType,
|
||||||
is_detected<key_type_t, ConstructibleObjectType>::value >>
|
enable_if_t<is_detected<mapped_type_t, ConstructibleObjectType>::value && is_detected<key_type_t, ConstructibleObjectType>::value>>
|
||||||
{
|
{
|
||||||
using object_t = typename BasicJsonType::object_t;
|
using object_t = typename BasicJsonType::object_t;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = (is_default_constructible<ConstructibleObjectType>::value &&
|
||||||
(is_default_constructible<ConstructibleObjectType>::value &&
|
(std::is_move_assignable<ConstructibleObjectType>::value || std::is_copy_assignable<ConstructibleObjectType>::value) &&
|
||||||
(std::is_move_assignable<ConstructibleObjectType>::value ||
|
(is_constructible<typename ConstructibleObjectType::key_type, typename object_t::key_type>::value &&
|
||||||
std::is_copy_assignable<ConstructibleObjectType>::value) &&
|
std::is_same<typename object_t::mapped_type, typename ConstructibleObjectType::mapped_type>::value)) ||
|
||||||
(is_constructible<typename ConstructibleObjectType::key_type,
|
(has_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value ||
|
||||||
typename object_t::key_type>::value &&
|
has_non_default_from_json<BasicJsonType, typename ConstructibleObjectType::mapped_type>::value);
|
||||||
std::is_same <
|
|
||||||
typename object_t::mapped_type,
|
|
||||||
typename ConstructibleObjectType::mapped_type >::value)) ||
|
|
||||||
(has_from_json<BasicJsonType,
|
|
||||||
typename ConstructibleObjectType::mapped_type>::value ||
|
|
||||||
has_non_default_from_json <
|
|
||||||
BasicJsonType,
|
|
||||||
typename ConstructibleObjectType::mapped_type >::value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleObjectType>
|
template<typename BasicJsonType, typename ConstructibleObjectType>
|
||||||
struct is_constructible_object_type
|
struct is_constructible_object_type : is_constructible_object_type_impl<BasicJsonType, ConstructibleObjectType>
|
||||||
: is_constructible_object_type_impl<BasicJsonType,
|
{};
|
||||||
ConstructibleObjectType> {};
|
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleStringType>
|
template<typename BasicJsonType, typename CompatibleStringType>
|
||||||
struct is_compatible_string_type
|
struct is_compatible_string_type
|
||||||
{
|
{
|
||||||
static constexpr auto value =
|
static constexpr auto value = is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
|
||||||
is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleStringType>
|
template<typename BasicJsonType, typename ConstructibleStringType>
|
||||||
@@ -417,174 +417,164 @@ struct is_constructible_string_type
|
|||||||
using laundered_type = ConstructibleStringType;
|
using laundered_type = ConstructibleStringType;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr auto value =
|
static constexpr auto value = conjunction<is_constructible<laundered_type, typename BasicJsonType::string_t>,
|
||||||
conjunction <
|
is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, laundered_type>>::value;
|
||||||
is_constructible<laundered_type, typename BasicJsonType::string_t>,
|
|
||||||
is_detected_exact<typename BasicJsonType::string_t::value_type,
|
|
||||||
value_type_t, laundered_type >>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
|
template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
|
||||||
struct is_compatible_array_type_impl : std::false_type {};
|
struct is_compatible_array_type_impl : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||||
struct is_compatible_array_type_impl <
|
struct is_compatible_array_type_impl<BasicJsonType,
|
||||||
BasicJsonType, CompatibleArrayType,
|
CompatibleArrayType,
|
||||||
enable_if_t <
|
enable_if_t<is_detected<iterator_t, CompatibleArrayType>::value &&
|
||||||
is_detected<iterator_t, CompatibleArrayType>::value&&
|
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value &&
|
||||||
is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
|
// special case for types like std::filesystem::path whose iterator's value_type are themselves
|
||||||
// special case for types like std::filesystem::path whose iterator's value_type are themselves
|
// c.f. https://github.com/nlohmann/json/pull/3073
|
||||||
// c.f. https://github.com/nlohmann/json/pull/3073
|
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value>>
|
||||||
!std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
|
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value = is_constructible<BasicJsonType, range_value_t<CompatibleArrayType>>::value;
|
||||||
is_constructible<BasicJsonType,
|
|
||||||
range_value_t<CompatibleArrayType>>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType>
|
template<typename BasicJsonType, typename CompatibleArrayType>
|
||||||
struct is_compatible_array_type
|
struct is_compatible_array_type : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType>
|
||||||
: is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
|
template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
|
||||||
struct is_constructible_array_type_impl : std::false_type {};
|
struct is_constructible_array_type_impl : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||||
struct is_constructible_array_type_impl <
|
struct is_constructible_array_type_impl<BasicJsonType,
|
||||||
BasicJsonType, ConstructibleArrayType,
|
ConstructibleArrayType,
|
||||||
enable_if_t<std::is_same<ConstructibleArrayType,
|
enable_if_t<std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value>> : std::true_type
|
||||||
typename BasicJsonType::value_type>::value >>
|
{};
|
||||||
: std::true_type {};
|
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||||
struct is_constructible_array_type_impl <
|
struct is_constructible_array_type_impl<
|
||||||
BasicJsonType, ConstructibleArrayType,
|
BasicJsonType,
|
||||||
enable_if_t < !std::is_same<ConstructibleArrayType,
|
ConstructibleArrayType,
|
||||||
typename BasicJsonType::value_type>::value&&
|
enable_if_t<!std::is_same<ConstructibleArrayType, typename BasicJsonType::value_type>::value &&
|
||||||
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
|
!is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value && is_default_constructible<ConstructibleArrayType>::value &&
|
||||||
is_default_constructible<ConstructibleArrayType>::value&&
|
(std::is_move_assignable<ConstructibleArrayType>::value || std::is_copy_assignable<ConstructibleArrayType>::value) &&
|
||||||
(std::is_move_assignable<ConstructibleArrayType>::value ||
|
is_detected<iterator_t, ConstructibleArrayType>::value &&
|
||||||
std::is_copy_assignable<ConstructibleArrayType>::value)&&
|
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value &&
|
||||||
is_detected<iterator_t, ConstructibleArrayType>::value&&
|
is_detected<range_value_t, ConstructibleArrayType>::value &&
|
||||||
is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
|
// special case for types like std::filesystem::path whose iterator's value_type are themselves
|
||||||
is_detected<range_value_t, ConstructibleArrayType>::value&&
|
// c.f. https://github.com/nlohmann/json/pull/3073
|
||||||
// special case for types like std::filesystem::path whose iterator's value_type are themselves
|
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value &&
|
||||||
// c.f. https://github.com/nlohmann/json/pull/3073
|
is_complete_type<detected_t<range_value_t, ConstructibleArrayType>>::value>>
|
||||||
!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
|
|
||||||
is_complete_type <
|
|
||||||
detected_t<range_value_t, ConstructibleArrayType >>::value >>
|
|
||||||
{
|
{
|
||||||
using value_type = range_value_t<ConstructibleArrayType>;
|
using value_type = range_value_t<ConstructibleArrayType>;
|
||||||
|
|
||||||
static constexpr bool value =
|
static constexpr bool value = std::is_same<value_type, typename BasicJsonType::array_t::value_type>::value ||
|
||||||
std::is_same<value_type,
|
has_from_json<BasicJsonType, value_type>::value || has_non_default_from_json<BasicJsonType, value_type>::value;
|
||||||
typename BasicJsonType::array_t::value_type>::value ||
|
|
||||||
has_from_json<BasicJsonType,
|
|
||||||
value_type>::value ||
|
|
||||||
has_non_default_from_json <
|
|
||||||
BasicJsonType,
|
|
||||||
value_type >::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename ConstructibleArrayType>
|
template<typename BasicJsonType, typename ConstructibleArrayType>
|
||||||
struct is_constructible_array_type
|
struct is_constructible_array_type : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType>
|
||||||
: is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
|
{};
|
||||||
|
|
||||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType,
|
template<typename RealIntegerType, typename CompatibleNumberIntegerType, typename = void>
|
||||||
typename = void>
|
struct is_compatible_integer_type_impl : std::false_type
|
||||||
struct is_compatible_integer_type_impl : std::false_type {};
|
{};
|
||||||
|
|
||||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||||
struct is_compatible_integer_type_impl <
|
struct is_compatible_integer_type_impl<RealIntegerType,
|
||||||
RealIntegerType, CompatibleNumberIntegerType,
|
CompatibleNumberIntegerType,
|
||||||
enable_if_t < std::is_integral<RealIntegerType>::value&&
|
enable_if_t<std::is_integral<RealIntegerType>::value && std::is_integral<CompatibleNumberIntegerType>::value &&
|
||||||
std::is_integral<CompatibleNumberIntegerType>::value&&
|
!std::is_same<bool, CompatibleNumberIntegerType>::value>>
|
||||||
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
|
||||||
{
|
{
|
||||||
// is there an assert somewhere on overflows?
|
// is there an assert somewhere on overflows?
|
||||||
using RealLimits = std::numeric_limits<RealIntegerType>;
|
using RealLimits = std::numeric_limits<RealIntegerType>;
|
||||||
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
|
using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
|
||||||
|
|
||||||
static constexpr auto value =
|
static constexpr auto value = is_constructible<RealIntegerType, CompatibleNumberIntegerType>::value && CompatibleLimits::is_integer &&
|
||||||
is_constructible<RealIntegerType,
|
RealLimits::is_signed == CompatibleLimits::is_signed;
|
||||||
CompatibleNumberIntegerType>::value &&
|
|
||||||
CompatibleLimits::is_integer &&
|
|
||||||
RealLimits::is_signed == CompatibleLimits::is_signed;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||||
struct is_compatible_integer_type
|
struct is_compatible_integer_type : is_compatible_integer_type_impl<RealIntegerType, CompatibleNumberIntegerType>
|
||||||
: is_compatible_integer_type_impl<RealIntegerType,
|
{};
|
||||||
CompatibleNumberIntegerType> {};
|
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleType, typename = void>
|
template<typename BasicJsonType, typename CompatibleType, typename = void>
|
||||||
struct is_compatible_type_impl: std::false_type {};
|
struct is_compatible_type_impl : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleType>
|
template<typename BasicJsonType, typename CompatibleType>
|
||||||
struct is_compatible_type_impl <
|
struct is_compatible_type_impl<BasicJsonType, CompatibleType, enable_if_t<is_complete_type<CompatibleType>::value>>
|
||||||
BasicJsonType, CompatibleType,
|
|
||||||
enable_if_t<is_complete_type<CompatibleType>::value >>
|
|
||||||
{
|
{
|
||||||
static constexpr bool value =
|
static constexpr bool value = has_to_json<BasicJsonType, CompatibleType>::value;
|
||||||
has_to_json<BasicJsonType, CompatibleType>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleType>
|
template<typename BasicJsonType, typename CompatibleType>
|
||||||
struct is_compatible_type
|
struct is_compatible_type : is_compatible_type_impl<BasicJsonType, CompatibleType>
|
||||||
: is_compatible_type_impl<BasicJsonType, CompatibleType> {};
|
{};
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
struct is_constructible_tuple : std::false_type {};
|
struct is_constructible_tuple : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T1, typename... Args>
|
template<typename T1, typename... Args>
|
||||||
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
|
struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...>
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T>
|
template<typename BasicJsonType, typename T>
|
||||||
struct is_json_iterator_of : std::false_type {};
|
struct is_json_iterator_of : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
|
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
|
||||||
{};
|
{};
|
||||||
|
|
||||||
// checks if a given type T is a template specialization of Primary
|
// checks if a given type T is a template specialization of Primary
|
||||||
template<template <typename...> class Primary, typename T>
|
template<template<typename...> class Primary, typename T>
|
||||||
struct is_specialization_of : std::false_type {};
|
struct is_specialization_of : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<template <typename...> class Primary, typename... Args>
|
template<template<typename...> class Primary, typename... Args>
|
||||||
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
|
struct is_specialization_of<Primary, Primary<Args...>> : std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
|
||||||
|
|
||||||
// checks if A and B are comparable using Compare functor
|
// checks if A and B are comparable using Compare functor
|
||||||
template<typename Compare, typename A, typename B, typename = void>
|
template<typename Compare, typename A, typename B, typename = void>
|
||||||
struct is_comparable : std::false_type {};
|
struct is_comparable : std::false_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename Compare, typename A, typename B>
|
template<typename Compare, typename A, typename B>
|
||||||
struct is_comparable<Compare, A, B, void_t<
|
struct is_comparable<
|
||||||
decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
Compare,
|
||||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
A,
|
||||||
>> : std::true_type {};
|
B,
|
||||||
|
void_t<decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())), decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))>>
|
||||||
|
: std::true_type
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using detect_is_transparent = typename T::is_transparent;
|
using detect_is_transparent = typename T::is_transparent;
|
||||||
|
|
||||||
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
|
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
|
||||||
// see is_usable_as_basic_json_key_type below
|
// see is_usable_as_basic_json_key_type below
|
||||||
template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
template<typename Comparator,
|
||||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
typename ObjectKeyType,
|
||||||
using is_usable_as_key_type = typename std::conditional <
|
typename KeyTypeCVRef,
|
||||||
is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
|
bool RequireTransparentComparator = true,
|
||||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
bool ExcludeObjectKeyType = RequireTransparentComparator,
|
||||||
ObjectKeyType>::value)
|
typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||||
&& (!RequireTransparentComparator
|
using is_usable_as_key_type =
|
||||||
|| is_detected <detect_is_transparent, Comparator>::value)
|
typename std::conditional<is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value &&
|
||||||
&& !is_json_pointer<KeyType>::value,
|
!(ExcludeObjectKeyType && std::is_same<KeyType, ObjectKeyType>::value) &&
|
||||||
|
(!RequireTransparentComparator || is_detected<detect_is_transparent, Comparator>::value) && !is_json_pointer<KeyType>::value,
|
||||||
std::true_type,
|
std::true_type,
|
||||||
std::false_type >::type;
|
std::false_type>::type;
|
||||||
|
|
||||||
// type trait to check if KeyType can be used as object key
|
// type trait to check if KeyType can be used as object key
|
||||||
// true if:
|
// true if:
|
||||||
@@ -592,48 +582,53 @@ using is_usable_as_key_type = typename std::conditional <
|
|||||||
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
|
||||||
// - the comparator is transparent or RequireTransparentComparator is false
|
// - the comparator is transparent or RequireTransparentComparator is false
|
||||||
// - KeyType is not a JSON iterator or json_pointer
|
// - KeyType is not a JSON iterator or json_pointer
|
||||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
template<typename BasicJsonType,
|
||||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
typename KeyTypeCVRef,
|
||||||
using is_usable_as_basic_json_key_type = typename std::conditional <
|
bool RequireTransparentComparator = true,
|
||||||
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
|
bool ExcludeObjectKeyType = RequireTransparentComparator,
|
||||||
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
|
typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||||
RequireTransparentComparator, ExcludeObjectKeyType>::value
|
using is_usable_as_basic_json_key_type = typename std::conditional<is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
|
||||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
|
typename BasicJsonType::object_t::key_type,
|
||||||
std::true_type,
|
KeyTypeCVRef,
|
||||||
std::false_type >::type;
|
RequireTransparentComparator,
|
||||||
|
ExcludeObjectKeyType>::value &&
|
||||||
|
!is_json_iterator_of<BasicJsonType, KeyType>::value,
|
||||||
|
std::true_type,
|
||||||
|
std::false_type>::type;
|
||||||
|
|
||||||
template<typename ObjectType, typename KeyType>
|
template<typename ObjectType, typename KeyType>
|
||||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||||
|
|
||||||
// type trait to check if object_t has an erase() member functions accepting KeyType
|
// type trait to check if object_t has an erase() member functions accepting KeyType
|
||||||
template<typename BasicJsonType, typename KeyType>
|
template<typename BasicJsonType, typename KeyType>
|
||||||
using has_erase_with_key_type = typename std::conditional <
|
using has_erase_with_key_type =
|
||||||
is_detected <
|
typename std::conditional<is_detected<detect_erase_with_key_type, typename BasicJsonType::object_t, KeyType>::value, std::true_type, std::false_type>::type;
|
||||||
detect_erase_with_key_type,
|
|
||||||
typename BasicJsonType::object_t, KeyType >::value,
|
|
||||||
std::true_type,
|
|
||||||
std::false_type >::type;
|
|
||||||
|
|
||||||
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
// a naive helper to check if a type is an ordered_map (exploits the fact that
|
||||||
// ordered_map inherits capacity() from std::vector)
|
// ordered_map inherits capacity() from std::vector)
|
||||||
template <typename T>
|
template<typename T>
|
||||||
struct is_ordered_map
|
struct is_ordered_map
|
||||||
{
|
{
|
||||||
using one = char;
|
using one = char;
|
||||||
|
|
||||||
struct two
|
struct two
|
||||||
{
|
{
|
||||||
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename C> static one test( decltype(&C::capacity) ) ;
|
template<typename C>
|
||||||
template <typename C> static two test(...);
|
static one test(decltype(&C::capacity));
|
||||||
|
template<typename C>
|
||||||
|
static two test(...);
|
||||||
|
|
||||||
enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
enum
|
||||||
|
{
|
||||||
|
value = sizeof(test<T>(nullptr)) == sizeof(char)
|
||||||
|
}; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
};
|
};
|
||||||
|
|
||||||
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
|
// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
|
||||||
template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
|
template<typename T, typename U, enable_if_t<!std::is_same<T, U>::value, int> = 0>
|
||||||
T conditional_static_cast(U value)
|
T conditional_static_cast(U value)
|
||||||
{
|
{
|
||||||
return static_cast<T>(value);
|
return static_cast<T>(value);
|
||||||
@@ -656,17 +651,14 @@ using all_unsigned = conjunction<std::is_unsigned<Types>...>;
|
|||||||
|
|
||||||
// there's a disjunction trait in another PR; replace when merged
|
// there's a disjunction trait in another PR; replace when merged
|
||||||
template<typename... Types>
|
template<typename... Types>
|
||||||
using same_sign = std::integral_constant < bool,
|
using same_sign = std::integral_constant<bool, all_signed<Types...>::value || all_unsigned<Types...>::value>;
|
||||||
all_signed<Types...>::value || all_unsigned<Types...>::value >;
|
|
||||||
|
|
||||||
template<typename OfType, typename T>
|
template<typename OfType, typename T>
|
||||||
using never_out_of_range = std::integral_constant < bool,
|
using never_out_of_range =
|
||||||
(std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
|
std::integral_constant<bool,
|
||||||
|| (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
|
(std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType))) || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T))>;
|
||||||
|
|
||||||
template<typename OfType, typename T,
|
template<typename OfType, typename T, bool OfTypeSigned = std::is_signed<OfType>::value, bool TSigned = std::is_signed<T>::value>
|
||||||
bool OfTypeSigned = std::is_signed<OfType>::value,
|
|
||||||
bool TSigned = std::is_signed<T>::value>
|
|
||||||
struct value_in_range_of_impl2;
|
struct value_in_range_of_impl2;
|
||||||
|
|
||||||
template<typename OfType, typename T>
|
template<typename OfType, typename T>
|
||||||
@@ -705,12 +697,13 @@ struct value_in_range_of_impl2<OfType, T, true, true>
|
|||||||
static constexpr bool test(T val)
|
static constexpr bool test(T val)
|
||||||
{
|
{
|
||||||
using CommonType = typename std::common_type<OfType, T>::type;
|
using CommonType = typename std::common_type<OfType, T>::type;
|
||||||
return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
|
return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)()) &&
|
||||||
&& static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
|
static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename OfType, typename T,
|
template<typename OfType,
|
||||||
|
typename T,
|
||||||
bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
|
bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
|
||||||
typename = detail::enable_if_t<all_integral<OfType, T>::value>>
|
typename = detail::enable_if_t<all_integral<OfType, T>::value>>
|
||||||
struct value_in_range_of_impl1;
|
struct value_in_range_of_impl1;
|
||||||
@@ -756,16 +749,15 @@ inline constexpr bool is_c_string()
|
|||||||
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
|
using TUnCVExt = typename std::remove_cv<TUnExt>::type;
|
||||||
using TUnPtr = typename std::remove_pointer<T>::type;
|
using TUnPtr = typename std::remove_pointer<T>::type;
|
||||||
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
|
using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
|
||||||
return
|
return (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value) || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
|
||||||
(std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
|
|
||||||
|| (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace impl
|
} // namespace impl
|
||||||
|
|
||||||
// checks whether T is a [cv] char */[cv] char[] C string
|
// checks whether T is a [cv] char */[cv] char[] C string
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
|
struct is_c_string : bool_constant<impl::is_c_string<T>()>
|
||||||
|
{};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
|
using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
|
||||||
@@ -787,7 +779,8 @@ inline constexpr bool is_transparent()
|
|||||||
|
|
||||||
// checks whether T has a member named is_transparent
|
// checks whether T has a member named is_transparent
|
||||||
template<typename T>
|
template<typename T>
|
||||||
struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
|
struct is_transparent : bool_constant<impl::is_transparent<T>()>
|
||||||
|
{};
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
|
|
||||||
template<typename ...Ts> struct make_void
|
template<typename... Ts>
|
||||||
|
struct make_void
|
||||||
{
|
{
|
||||||
using type = void;
|
using type = void;
|
||||||
};
|
};
|
||||||
template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
|
template<typename... Ts>
|
||||||
|
using void_t = typename make_void<Ts...>::type;
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|||||||
@@ -8,16 +8,16 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // reverse
|
#include <algorithm> // reverse
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <map> // map
|
#include <cmath> // isnan, isinf
|
||||||
#include <cmath> // isnan, isinf
|
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
||||||
#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
|
#include <cstring> // memcpy
|
||||||
#include <cstring> // memcpy
|
#include <limits> // numeric_limits
|
||||||
#include <limits> // numeric_limits
|
#include <map> // map
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/input/binary_reader.hpp>
|
#include <nlohmann/detail/input/binary_reader.hpp>
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -48,7 +48,8 @@ class binary_writer
|
|||||||
|
|
||||||
@param[in] adapter output adapter to write to
|
@param[in] adapter output adapter to write to
|
||||||
*/
|
*/
|
||||||
explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
|
explicit binary_writer(output_adapter_t<CharType> adapter)
|
||||||
|
: oa(std::move(adapter))
|
||||||
{
|
{
|
||||||
JSON_ASSERT(oa);
|
JSON_ASSERT(oa);
|
||||||
}
|
}
|
||||||
@@ -98,9 +99,7 @@ class binary_writer
|
|||||||
|
|
||||||
case value_t::boolean:
|
case value_t::boolean:
|
||||||
{
|
{
|
||||||
oa->write_character(j.m_data.m_value.boolean
|
oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xF5) : to_char_type(0xF4));
|
||||||
? to_char_type(0xF5)
|
|
||||||
: to_char_type(0xF4));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,9 +252,7 @@ class binary_writer
|
|||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// step 2: write the string
|
// step 2: write the string
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
|
|
||||||
j.m_data.m_value.string->size());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,9 +351,7 @@ class binary_writer
|
|||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// step 2: write each element
|
// step 2: write each element
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
|
|
||||||
N);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -414,17 +409,15 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
case value_t::null: // nil
|
case value_t::null: // nil
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(0xC0));
|
oa->write_character(to_char_type(0xC0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::boolean: // true and false
|
case value_t::boolean: // true and false
|
||||||
{
|
{
|
||||||
oa->write_character(j.m_data.m_value.boolean
|
oa->write_character(j.m_data.m_value.boolean ? to_char_type(0xC3) : to_char_type(0xC2));
|
||||||
? to_char_type(0xC3)
|
|
||||||
: to_char_type(0xC2));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,9 +566,7 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// step 2: write the string
|
// step 2: write the string
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
|
|
||||||
j.m_data.m_value.string->size());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -626,30 +617,29 @@ class binary_writer
|
|||||||
switch (N)
|
switch (N)
|
||||||
{
|
{
|
||||||
case 1:
|
case 1:
|
||||||
output_type = 0xD4; // fixext 1
|
output_type = 0xD4; // fixext 1
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
output_type = 0xD5; // fixext 2
|
output_type = 0xD5; // fixext 2
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
output_type = 0xD6; // fixext 4
|
output_type = 0xD6; // fixext 4
|
||||||
break;
|
break;
|
||||||
case 8:
|
case 8:
|
||||||
output_type = 0xD7; // fixext 8
|
output_type = 0xD7; // fixext 8
|
||||||
break;
|
break;
|
||||||
case 16:
|
case 16:
|
||||||
output_type = 0xD8; // fixext 16
|
output_type = 0xD8; // fixext 16
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
output_type = 0xC7; // ext 8
|
output_type = 0xC7; // ext 8
|
||||||
fixed = false;
|
fixed = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
output_type = 0xC4; // bin 8
|
output_type = 0xC4; // bin 8
|
||||||
fixed = false;
|
fixed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,18 +651,16 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
else if (N <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
{
|
{
|
||||||
const std::uint8_t output_type = use_ext
|
const std::uint8_t output_type = use_ext ? 0xC8 // ext 16
|
||||||
? 0xC8 // ext 16
|
: 0xC5; // bin 16
|
||||||
: 0xC5; // bin 16
|
|
||||||
|
|
||||||
oa->write_character(to_char_type(output_type));
|
oa->write_character(to_char_type(output_type));
|
||||||
write_number(static_cast<std::uint16_t>(N));
|
write_number(static_cast<std::uint16_t>(N));
|
||||||
}
|
}
|
||||||
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
else if (N <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
{
|
{
|
||||||
const std::uint8_t output_type = use_ext
|
const std::uint8_t output_type = use_ext ? 0xC9 // ext 32
|
||||||
? 0xC9 // ext 32
|
: 0xC6; // bin 32
|
||||||
: 0xC6; // bin 32
|
|
||||||
|
|
||||||
oa->write_character(to_char_type(output_type));
|
oa->write_character(to_char_type(output_type));
|
||||||
write_number(static_cast<std::uint32_t>(N));
|
write_number(static_cast<std::uint32_t>(N));
|
||||||
@@ -685,9 +673,7 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// step 2: write the byte string
|
// step 2: write the byte string
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), N);
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
|
|
||||||
N);
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -736,9 +722,7 @@ class binary_writer
|
|||||||
@param[in] add_prefix whether prefixes need to be used for this value
|
@param[in] add_prefix whether prefixes need to be used for this value
|
||||||
@param[in] use_bjdata whether write in BJData format, default is false
|
@param[in] use_bjdata whether write in BJData format, default is false
|
||||||
*/
|
*/
|
||||||
void write_ubjson(const BasicJsonType& j, const bool use_count,
|
void write_ubjson(const BasicJsonType& j, const bool use_count, const bool use_type, const bool add_prefix = true, const bool use_bjdata = false)
|
||||||
const bool use_type, const bool add_prefix = true,
|
|
||||||
const bool use_bjdata = false)
|
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
@@ -755,9 +739,7 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
oa->write_character(j.m_data.m_value.boolean
|
oa->write_character(j.m_data.m_value.boolean ? to_char_type('T') : to_char_type('F'));
|
||||||
? to_char_type('T')
|
|
||||||
: to_char_type('F'));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -787,9 +769,7 @@ class binary_writer
|
|||||||
oa->write_character(to_char_type('S'));
|
oa->write_character(to_char_type('S'));
|
||||||
}
|
}
|
||||||
write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
|
write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()), j.m_data.m_value.string->size());
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
|
|
||||||
j.m_data.m_value.string->size());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,13 +785,11 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(use_count);
|
JSON_ASSERT(use_count);
|
||||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||||
const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
|
const bool same_prefix = std::all_of(j.begin() + 1, j.end(), [this, first_prefix, use_bjdata](const BasicJsonType& v) {
|
||||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
|
||||||
{
|
|
||||||
return ubjson_prefix(v, use_bjdata) == first_prefix;
|
return ubjson_prefix(v, use_bjdata) == first_prefix;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
|
std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
|
||||||
|
|
||||||
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
|
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
|
||||||
{
|
{
|
||||||
@@ -862,9 +840,7 @@ class binary_writer
|
|||||||
|
|
||||||
if (use_type)
|
if (use_type)
|
||||||
{
|
{
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()), j.m_data.m_value.binary->size());
|
||||||
reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
|
|
||||||
j.m_data.m_value.binary->size());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -885,9 +861,13 @@ class binary_writer
|
|||||||
|
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
{
|
{
|
||||||
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
|
if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() &&
|
||||||
|
j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() &&
|
||||||
|
j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
|
||||||
{
|
{
|
||||||
if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
|
if (!write_bjdata_ndarray(*j.m_data.m_value.object,
|
||||||
|
use_count,
|
||||||
|
use_type)) // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -903,13 +883,11 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
JSON_ASSERT(use_count);
|
JSON_ASSERT(use_count);
|
||||||
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
|
||||||
const bool same_prefix = std::all_of(j.begin(), j.end(),
|
const bool same_prefix = std::all_of(j.begin(), j.end(), [this, first_prefix, use_bjdata](const BasicJsonType& v) {
|
||||||
[this, first_prefix, use_bjdata](const BasicJsonType & v)
|
|
||||||
{
|
|
||||||
return ubjson_prefix(v, use_bjdata) == first_prefix;
|
return ubjson_prefix(v, use_bjdata) == first_prefix;
|
||||||
});
|
});
|
||||||
|
|
||||||
std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
|
std::vector<CharType> bjdx = { '[', '{', 'S', 'H', 'T', 'F', 'N', 'Z' }; // excluded markers in bjdata optimized type
|
||||||
|
|
||||||
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
|
if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
|
||||||
{
|
{
|
||||||
@@ -928,9 +906,7 @@ class binary_writer
|
|||||||
for (const auto& el : *j.m_data.m_value.object)
|
for (const auto& el : *j.m_data.m_value.object)
|
||||||
{
|
{
|
||||||
write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
|
write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(el.first.c_str()), el.first.size());
|
||||||
reinterpret_cast<const CharType*>(el.first.c_str()),
|
|
||||||
el.first.size());
|
|
||||||
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
|
write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,26 +942,22 @@ class binary_writer
|
|||||||
static_cast<void>(j);
|
static_cast<void>(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
|
return /*id*/ 1ul + name.size() + /*zero-terminator*/ 1u;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Writes the given @a element_type and @a name to the output adapter
|
@brief Writes the given @a element_type and @a name to the output adapter
|
||||||
*/
|
*/
|
||||||
void write_bson_entry_header(const string_t& name,
|
void write_bson_entry_header(const string_t& name, const std::uint8_t element_type)
|
||||||
const std::uint8_t element_type)
|
|
||||||
{
|
{
|
||||||
oa->write_character(to_char_type(element_type)); // boolean
|
oa->write_character(to_char_type(element_type)); // boolean
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(name.c_str()), name.size() + 1u);
|
||||||
reinterpret_cast<const CharType*>(name.c_str()),
|
|
||||||
name.size() + 1u);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and boolean value @a value
|
@brief Writes a BSON element with key @a name and boolean value @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_boolean(const string_t& name,
|
void write_bson_boolean(const string_t& name, const bool value)
|
||||||
const bool value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x08);
|
write_bson_entry_header(name, 0x08);
|
||||||
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
|
oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
|
||||||
@@ -994,8 +966,7 @@ class binary_writer
|
|||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and double value @a value
|
@brief Writes a BSON element with key @a name and double value @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_double(const string_t& name,
|
void write_bson_double(const string_t& name, const double value)
|
||||||
const double value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x01);
|
write_bson_entry_header(name, 0x01);
|
||||||
write_number<double>(value, true);
|
write_number<double>(value, true);
|
||||||
@@ -1012,15 +983,12 @@ class binary_writer
|
|||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and string value @a value
|
@brief Writes a BSON element with key @a name and string value @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_string(const string_t& name,
|
void write_bson_string(const string_t& name, const string_t& value)
|
||||||
const string_t& value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x02);
|
write_bson_entry_header(name, 0x02);
|
||||||
|
|
||||||
write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
|
write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
|
||||||
oa->write_characters(
|
oa->write_characters(reinterpret_cast<const CharType*>(value.c_str()), value.size() + 1);
|
||||||
reinterpret_cast<const CharType*>(value.c_str()),
|
|
||||||
value.size() + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -1036,25 +1004,23 @@ class binary_writer
|
|||||||
*/
|
*/
|
||||||
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
static std::size_t calc_bson_integer_size(const std::int64_t value)
|
||||||
{
|
{
|
||||||
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
|
return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)() ? sizeof(std::int32_t)
|
||||||
? sizeof(std::int32_t)
|
: sizeof(std::int64_t);
|
||||||
: sizeof(std::int64_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and integer @a value
|
@brief Writes a BSON element with key @a name and integer @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_integer(const string_t& name,
|
void write_bson_integer(const string_t& name, const std::int64_t value)
|
||||||
const std::int64_t value)
|
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
|
if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x10); // int32
|
write_bson_entry_header(name, 0x10); // int32
|
||||||
write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
|
write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x12); // int64
|
write_bson_entry_header(name, 0x12); // int64
|
||||||
write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
|
write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1064,16 +1030,13 @@ class binary_writer
|
|||||||
*/
|
*/
|
||||||
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
|
static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
|
||||||
{
|
{
|
||||||
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)())) ? sizeof(std::int32_t) : sizeof(std::int64_t);
|
||||||
? sizeof(std::int32_t)
|
|
||||||
: sizeof(std::int64_t);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and unsigned @a value
|
@brief Writes a BSON element with key @a name and unsigned @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_unsigned(const string_t& name,
|
void write_bson_unsigned(const string_t& name, const BasicJsonType& j)
|
||||||
const BasicJsonType& j)
|
|
||||||
{
|
{
|
||||||
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
|
||||||
{
|
{
|
||||||
@@ -1087,17 +1050,19 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
|
JSON_THROW(out_of_range::create(
|
||||||
|
407,
|
||||||
|
concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"),
|
||||||
|
&j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and object @a value
|
@brief Writes a BSON element with key @a name and object @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_object_entry(const string_t& name,
|
void write_bson_object_entry(const string_t& name, const typename BasicJsonType::object_t& value)
|
||||||
const typename BasicJsonType::object_t& value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x03); // object
|
write_bson_entry_header(name, 0x03); // object
|
||||||
write_bson_object(value);
|
write_bson_object(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1108,10 +1073,12 @@ class binary_writer
|
|||||||
{
|
{
|
||||||
std::size_t array_index = 0ul;
|
std::size_t array_index = 0ul;
|
||||||
|
|
||||||
const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
|
const std::size_t embedded_document_size = std::accumulate(std::begin(value),
|
||||||
{
|
std::end(value),
|
||||||
return result + calc_bson_element_size(std::to_string(array_index++), el);
|
static_cast<std::size_t>(0),
|
||||||
});
|
[&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type& el) {
|
||||||
|
return result + calc_bson_element_size(std::to_string(array_index++), el);
|
||||||
|
});
|
||||||
|
|
||||||
return sizeof(std::int32_t) + embedded_document_size + 1ul;
|
return sizeof(std::int32_t) + embedded_document_size + 1ul;
|
||||||
}
|
}
|
||||||
@@ -1127,10 +1094,9 @@ class binary_writer
|
|||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and array @a value
|
@brief Writes a BSON element with key @a name and array @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_array(const string_t& name,
|
void write_bson_array(const string_t& name, const typename BasicJsonType::array_t& value)
|
||||||
const typename BasicJsonType::array_t& value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x04); // array
|
write_bson_entry_header(name, 0x04); // array
|
||||||
write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
|
write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
|
||||||
|
|
||||||
std::size_t array_index = 0ul;
|
std::size_t array_index = 0ul;
|
||||||
@@ -1146,8 +1112,7 @@ class binary_writer
|
|||||||
/*!
|
/*!
|
||||||
@brief Writes a BSON element with key @a name and binary value @a value
|
@brief Writes a BSON element with key @a name and binary value @a value
|
||||||
*/
|
*/
|
||||||
void write_bson_binary(const string_t& name,
|
void write_bson_binary(const string_t& name, const binary_t& value)
|
||||||
const binary_t& value)
|
|
||||||
{
|
{
|
||||||
write_bson_entry_header(name, 0x05);
|
write_bson_entry_header(name, 0x05);
|
||||||
|
|
||||||
@@ -1161,8 +1126,7 @@ class binary_writer
|
|||||||
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
|
@brief Calculates the size necessary to serialize the JSON value @a j with its @a name
|
||||||
@return The calculated size for the BSON document entry for @a j with the given @a name.
|
@return The calculated size for the BSON document entry for @a j with the given @a name.
|
||||||
*/
|
*/
|
||||||
static std::size_t calc_bson_element_size(const string_t& name,
|
static std::size_t calc_bson_element_size(const string_t& name, const BasicJsonType& j)
|
||||||
const BasicJsonType& j)
|
|
||||||
{
|
{
|
||||||
const auto header_size = calc_bson_entry_header_size(name, j);
|
const auto header_size = calc_bson_entry_header_size(name, j);
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
@@ -1197,7 +1161,7 @@ class binary_writer
|
|||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
|
||||||
return 0ul;
|
return 0ul;
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
@@ -1209,8 +1173,7 @@ class binary_writer
|
|||||||
@param name The name to associate with the JSON entity @a j within the
|
@param name The name to associate with the JSON entity @a j within the
|
||||||
current BSON document
|
current BSON document
|
||||||
*/
|
*/
|
||||||
void write_bson_element(const string_t& name,
|
void write_bson_element(const string_t& name, const BasicJsonType& j)
|
||||||
const BasicJsonType& j)
|
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
@@ -1244,7 +1207,7 @@ class binary_writer
|
|||||||
// LCOV_EXCL_START
|
// LCOV_EXCL_START
|
||||||
case value_t::discarded:
|
case value_t::discarded:
|
||||||
default:
|
default:
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
|
||||||
return;
|
return;
|
||||||
// LCOV_EXCL_STOP
|
// LCOV_EXCL_STOP
|
||||||
}
|
}
|
||||||
@@ -1258,11 +1221,10 @@ class binary_writer
|
|||||||
*/
|
*/
|
||||||
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
|
static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
|
||||||
{
|
{
|
||||||
const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
|
const std::size_t document_size =
|
||||||
[](size_t result, const typename BasicJsonType::object_t::value_type & el)
|
std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0), [](size_t result, const typename BasicJsonType::object_t::value_type& el) {
|
||||||
{
|
return result += calc_bson_element_size(el.first, el.second);
|
||||||
return result += calc_bson_element_size(el.first, el.second);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
return sizeof(std::int32_t) + document_size + 1ul;
|
return sizeof(std::int32_t) + document_size + 1ul;
|
||||||
}
|
}
|
||||||
@@ -1316,11 +1278,8 @@ class binary_writer
|
|||||||
////////////
|
////////////
|
||||||
|
|
||||||
// UBJSON: write number (floating point)
|
// UBJSON: write number (floating point)
|
||||||
template<typename NumberType, typename std::enable_if<
|
template<typename NumberType, typename std::enable_if<std::is_floating_point<NumberType>::value, int>::type = 0>
|
||||||
std::is_floating_point<NumberType>::value, int>::type = 0>
|
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
|
||||||
const bool add_prefix,
|
|
||||||
const bool use_bjdata)
|
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -1330,11 +1289,8 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UBJSON: write number (unsigned integer)
|
// UBJSON: write number (unsigned integer)
|
||||||
template<typename NumberType, typename std::enable_if<
|
template<typename NumberType, typename std::enable_if<std::is_unsigned<NumberType>::value, int>::type = 0>
|
||||||
std::is_unsigned<NumberType>::value, int>::type = 0>
|
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
|
||||||
const bool add_prefix,
|
|
||||||
const bool use_bjdata)
|
|
||||||
{
|
{
|
||||||
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
|
if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
|
||||||
{
|
{
|
||||||
@@ -1417,12 +1373,8 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// UBJSON: write number (signed integer)
|
// UBJSON: write number (signed integer)
|
||||||
template < typename NumberType, typename std::enable_if <
|
template<typename NumberType, typename std::enable_if<std::is_signed<NumberType>::value && !std::is_floating_point<NumberType>::value, int>::type = 0>
|
||||||
std::is_signed<NumberType>::value&&
|
void write_number_with_ubjson_prefix(const NumberType n, const bool add_prefix, const bool use_bjdata)
|
||||||
!std::is_floating_point<NumberType>::value, int >::type = 0 >
|
|
||||||
void write_number_with_ubjson_prefix(const NumberType n,
|
|
||||||
const bool add_prefix,
|
|
||||||
const bool use_bjdata)
|
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
|
if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
@@ -1432,7 +1384,8 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<std::int8_t>(n), use_bjdata);
|
write_number(static_cast<std::int8_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n &&
|
||||||
|
n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -1448,7 +1401,8 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<std::int16_t>(n), use_bjdata);
|
write_number(static_cast<std::int16_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
|
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n &&
|
||||||
|
n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -1464,7 +1418,8 @@ class binary_writer
|
|||||||
}
|
}
|
||||||
write_number(static_cast<std::int32_t>(n), use_bjdata);
|
write_number(static_cast<std::int32_t>(n), use_bjdata);
|
||||||
}
|
}
|
||||||
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
|
else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n &&
|
||||||
|
n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
|
||||||
{
|
{
|
||||||
if (add_prefix)
|
if (add_prefix)
|
||||||
{
|
{
|
||||||
@@ -1513,36 +1468,43 @@ class binary_writer
|
|||||||
|
|
||||||
case value_t::number_integer:
|
case value_t::number_integer:
|
||||||
{
|
{
|
||||||
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
|
||||||
{
|
{
|
||||||
return 'i';
|
return 'i';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
{
|
{
|
||||||
return 'U';
|
return 'U';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
|
||||||
{
|
{
|
||||||
return 'I';
|
return 'I';
|
||||||
}
|
}
|
||||||
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
|
if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
|
||||||
{
|
{
|
||||||
return 'u';
|
return 'u';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
|
||||||
{
|
{
|
||||||
return 'l';
|
return 'l';
|
||||||
}
|
}
|
||||||
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
|
if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
|
||||||
{
|
{
|
||||||
return 'm';
|
return 'm';
|
||||||
}
|
}
|
||||||
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer &&
|
||||||
|
j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
|
||||||
{
|
{
|
||||||
return 'L';
|
return 'L';
|
||||||
}
|
}
|
||||||
// anything else is treated as high-precision number
|
// anything else is treated as high-precision number
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
return 'H'; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_unsigned:
|
case value_t::number_unsigned:
|
||||||
@@ -1580,7 +1542,7 @@ class binary_writer
|
|||||||
return 'M';
|
return 'M';
|
||||||
}
|
}
|
||||||
// anything else is treated as high-precision number
|
// anything else is treated as high-precision number
|
||||||
return 'H'; // LCOV_EXCL_LINE
|
return 'H'; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
case value_t::number_float:
|
case value_t::number_float:
|
||||||
@@ -1589,7 +1551,7 @@ class binary_writer
|
|||||||
case value_t::string:
|
case value_t::string:
|
||||||
return 'S';
|
return 'S';
|
||||||
|
|
||||||
case value_t::array: // fallthrough
|
case value_t::array: // fallthrough
|
||||||
case value_t::binary:
|
case value_t::binary:
|
||||||
return '[';
|
return '[';
|
||||||
|
|
||||||
@@ -1617,9 +1579,8 @@ class binary_writer
|
|||||||
*/
|
*/
|
||||||
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
|
bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
|
||||||
{
|
{
|
||||||
std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
|
std::map<string_t, CharType> bjdtype = { { "uint8", 'U' }, { "int8", 'i' }, { "uint16", 'u' }, { "int16", 'I' }, { "uint32", 'm' }, { "int32", 'l' },
|
||||||
{"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
|
{ "uint64", 'M' }, { "int64", 'L' }, { "single", 'd' }, { "double", 'D' }, { "char", 'C' } };
|
||||||
};
|
|
||||||
|
|
||||||
string_t key = "_ArrayType_";
|
string_t key = "_ArrayType_";
|
||||||
auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
|
auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
|
||||||
@@ -1648,7 +1609,7 @@ class binary_writer
|
|||||||
oa->write_character('#');
|
oa->write_character('#');
|
||||||
|
|
||||||
key = "_ArraySize_";
|
key = "_ArraySize_";
|
||||||
write_ubjson(value.at(key), use_count, use_type, true, true);
|
write_ubjson(value.at(key), use_count, use_type, true, true);
|
||||||
|
|
||||||
key = "_ArrayData_";
|
key = "_ArrayData_";
|
||||||
if (dtype == 'U' || dtype == 'C')
|
if (dtype == 'U' || dtype == 'C')
|
||||||
@@ -1761,27 +1722,24 @@ class binary_writer
|
|||||||
void write_compact_float(const number_float_t n, detail::input_format_t format)
|
void write_compact_float(const number_float_t n, detail::input_format_t format)
|
||||||
{
|
{
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
#pragma GCC diagnostic ignored "-Wfloat-equal"
|
||||||
#endif
|
#endif
|
||||||
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
|
||||||
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
|
||||||
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
|
static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
|
||||||
{
|
{
|
||||||
oa->write_character(format == detail::input_format_t::cbor
|
oa->write_character(format == detail::input_format_t::cbor ? get_cbor_float_prefix(static_cast<float>(n))
|
||||||
? get_cbor_float_prefix(static_cast<float>(n))
|
: get_msgpack_float_prefix(static_cast<float>(n)));
|
||||||
: get_msgpack_float_prefix(static_cast<float>(n)));
|
|
||||||
write_number(static_cast<float>(n));
|
write_number(static_cast<float>(n));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
oa->write_character(format == detail::input_format_t::cbor
|
oa->write_character(format == detail::input_format_t::cbor ? get_cbor_float_prefix(n) : get_msgpack_float_prefix(n));
|
||||||
? get_cbor_float_prefix(n)
|
|
||||||
: get_msgpack_float_prefix(n));
|
|
||||||
write_number(n);
|
write_number(n);
|
||||||
}
|
}
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1790,15 +1748,13 @@ class binary_writer
|
|||||||
// between uint8_t and CharType. In case CharType is not unsigned,
|
// between uint8_t and CharType. In case CharType is not unsigned,
|
||||||
// such a conversion is required to allow values greater than 128.
|
// such a conversion is required to allow values greater than 128.
|
||||||
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
|
// See <https://github.com/nlohmann/json/issues/1286> for a discussion.
|
||||||
template < typename C = CharType,
|
template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value>* = nullptr>
|
||||||
enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
|
|
||||||
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
||||||
{
|
{
|
||||||
return *reinterpret_cast<char*>(&x);
|
return *reinterpret_cast<char*>(&x);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename C = CharType,
|
template<typename C = CharType, enable_if_t<std::is_signed<C>::value && std::is_unsigned<char>::value>* = nullptr>
|
||||||
enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
|
|
||||||
static CharType to_char_type(std::uint8_t x) noexcept
|
static CharType to_char_type(std::uint8_t x) noexcept
|
||||||
{
|
{
|
||||||
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
|
static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
|
||||||
@@ -1808,19 +1764,16 @@ class binary_writer
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename C = CharType,
|
template<typename C = CharType, enable_if_t<std::is_unsigned<C>::value>* = nullptr>
|
||||||
enable_if_t<std::is_unsigned<C>::value>* = nullptr>
|
|
||||||
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
static constexpr CharType to_char_type(std::uint8_t x) noexcept
|
||||||
{
|
{
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename InputCharType, typename C = CharType,
|
template<typename InputCharType,
|
||||||
enable_if_t <
|
typename C = CharType,
|
||||||
std::is_signed<C>::value &&
|
enable_if_t<std::is_signed<C>::value && std::is_signed<char>::value && std::is_same<char, typename std::remove_cv<InputCharType>::type>::value>* =
|
||||||
std::is_signed<char>::value &&
|
nullptr>
|
||||||
std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
|
|
||||||
> * = nullptr >
|
|
||||||
static constexpr CharType to_char_type(InputCharType x) noexcept
|
static constexpr CharType to_char_type(InputCharType x) noexcept
|
||||||
{
|
{
|
||||||
return x;
|
return x;
|
||||||
|
|||||||
@@ -8,17 +8,17 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // copy
|
#include <algorithm> // copy
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <iterator> // back_inserter
|
#include <iterator> // back_inserter
|
||||||
#include <memory> // shared_ptr, make_shared
|
#include <memory> // shared_ptr, make_shared
|
||||||
#include <string> // basic_string
|
#include <string> // basic_string
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
#include <ios> // streamsize
|
#include <ios> // streamsize
|
||||||
#include <ostream> // basic_ostream
|
#include <ostream> // basic_ostream
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
|
|
||||||
@@ -27,7 +27,8 @@ namespace detail
|
|||||||
{
|
{
|
||||||
|
|
||||||
/// abstract output adapter interface
|
/// abstract output adapter interface
|
||||||
template<typename CharType> struct output_adapter_protocol
|
template<typename CharType>
|
||||||
|
struct output_adapter_protocol
|
||||||
{
|
{
|
||||||
virtual void write_character(CharType c) = 0;
|
virtual void write_character(CharType c) = 0;
|
||||||
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
virtual void write_characters(const CharType* s, std::size_t length) = 0;
|
||||||
@@ -50,7 +51,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
|
explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
|
||||||
: v(vec)
|
: v(vec)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void write_character(CharType c) override
|
void write_character(CharType c) override
|
||||||
@@ -75,7 +76,7 @@ class output_stream_adapter : public output_adapter_protocol<CharType>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
|
explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
|
||||||
: stream(s)
|
: stream(s)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void write_character(CharType c) override
|
void write_character(CharType c) override
|
||||||
@@ -100,7 +101,7 @@ class output_string_adapter : public output_adapter_protocol<CharType>
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit output_string_adapter(StringType& s) noexcept
|
explicit output_string_adapter(StringType& s) noexcept
|
||||||
: str(s)
|
: str(s)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void write_character(CharType c) override
|
void write_character(CharType c) override
|
||||||
@@ -124,15 +125,18 @@ class output_adapter
|
|||||||
public:
|
public:
|
||||||
template<typename AllocatorType = std::allocator<CharType>>
|
template<typename AllocatorType = std::allocator<CharType>>
|
||||||
output_adapter(std::vector<CharType, AllocatorType>& vec)
|
output_adapter(std::vector<CharType, AllocatorType>& vec)
|
||||||
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
|
: oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec))
|
||||||
|
{}
|
||||||
|
|
||||||
#ifndef JSON_NO_IO
|
#ifndef JSON_NO_IO
|
||||||
output_adapter(std::basic_ostream<CharType>& s)
|
output_adapter(std::basic_ostream<CharType>& s)
|
||||||
: oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
|
: oa(std::make_shared<output_stream_adapter<CharType>>(s))
|
||||||
|
{}
|
||||||
#endif // JSON_NO_IO
|
#endif // JSON_NO_IO
|
||||||
|
|
||||||
output_adapter(StringType& s)
|
output_adapter(StringType& s)
|
||||||
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
|
: oa(std::make_shared<output_string_adapter<CharType, StringType>>(s))
|
||||||
|
{}
|
||||||
|
|
||||||
operator output_adapter_t<CharType>()
|
operator output_adapter_t<CharType>()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,18 +9,18 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // reverse, remove, fill, find, none_of
|
#include <algorithm> // reverse, remove, fill, find, none_of
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <clocale> // localeconv, lconv
|
#include <clocale> // localeconv, lconv
|
||||||
#include <cmath> // labs, isfinite, isnan, signbit
|
#include <cmath> // labs, isfinite, isnan, signbit
|
||||||
#include <cstddef> // size_t, ptrdiff_t
|
#include <cstddef> // size_t, ptrdiff_t
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <cstdio> // snprintf
|
#include <cstdio> // snprintf
|
||||||
#include <limits> // numeric_limits
|
#include <iomanip> // setfill, setw
|
||||||
#include <string> // string, char_traits
|
#include <limits> // numeric_limits
|
||||||
#include <iomanip> // setfill, setw
|
#include <string> // string, char_traits
|
||||||
#include <type_traits> // is_same
|
#include <type_traits> // is_same
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
#include <nlohmann/detail/conversions/to_chars.hpp>
|
#include <nlohmann/detail/conversions/to_chars.hpp>
|
||||||
#include <nlohmann/detail/exceptions.hpp>
|
#include <nlohmann/detail/exceptions.hpp>
|
||||||
@@ -42,9 +42,9 @@ namespace detail
|
|||||||
/// how to treat decoding errors
|
/// how to treat decoding errors
|
||||||
enum class error_handler_t
|
enum class error_handler_t
|
||||||
{
|
{
|
||||||
strict, ///< throw a type_error exception in case of invalid UTF-8
|
strict, ///< throw a type_error exception in case of invalid UTF-8
|
||||||
replace, ///< replace invalid UTF-8 sequences with U+FFFD
|
replace, ///< replace invalid UTF-8 sequences with U+FFFD
|
||||||
ignore ///< ignore invalid UTF-8 sequences
|
ignore ///< ignore invalid UTF-8 sequences
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename BasicJsonType>
|
template<typename BasicJsonType>
|
||||||
@@ -64,15 +64,14 @@ class serializer
|
|||||||
@param[in] ichar indentation character to use
|
@param[in] ichar indentation character to use
|
||||||
@param[in] error_handler_ how to react on decoding errors
|
@param[in] error_handler_ how to react on decoding errors
|
||||||
*/
|
*/
|
||||||
serializer(output_adapter_t<char> s, const char ichar,
|
serializer(output_adapter_t<char> s, const char ichar, error_handler_t error_handler_ = error_handler_t::strict)
|
||||||
error_handler_t error_handler_ = error_handler_t::strict)
|
: o(std::move(s))
|
||||||
: o(std::move(s))
|
, loc(std::localeconv())
|
||||||
, loc(std::localeconv())
|
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->thousands_sep)))
|
||||||
, thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
|
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(*(loc->decimal_point)))
|
||||||
, decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
|
, indent_char(ichar)
|
||||||
, indent_char(ichar)
|
, indent_string(512, indent_char)
|
||||||
, indent_string(512, indent_char)
|
, error_handler(error_handler_)
|
||||||
, error_handler(error_handler_)
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
// delete because of pointer members
|
// delete because of pointer members
|
||||||
@@ -104,11 +103,7 @@ class serializer
|
|||||||
@param[in] indent_step the indent level
|
@param[in] indent_step the indent level
|
||||||
@param[in] current_indent the current indent level (only used internally)
|
@param[in] current_indent the current indent level (only used internally)
|
||||||
*/
|
*/
|
||||||
void dump(const BasicJsonType& val,
|
void dump(const BasicJsonType& val, const bool pretty_print, const bool ensure_ascii, const unsigned int indent_step, const unsigned int current_indent = 0)
|
||||||
const bool pretty_print,
|
|
||||||
const bool ensure_ascii,
|
|
||||||
const unsigned int indent_step,
|
|
||||||
const unsigned int current_indent = 0)
|
|
||||||
{
|
{
|
||||||
switch (val.m_data.m_type)
|
switch (val.m_data.m_type)
|
||||||
{
|
{
|
||||||
@@ -205,8 +200,7 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// first n-1 elements
|
// first n-1 elements
|
||||||
for (auto i = val.m_data.m_value.array->cbegin();
|
for (auto i = val.m_data.m_value.array->cbegin(); i != val.m_data.m_value.array->cend() - 1; ++i)
|
||||||
i != val.m_data.m_value.array->cend() - 1; ++i)
|
|
||||||
{
|
{
|
||||||
o->write_characters(indent_string.c_str(), new_indent);
|
o->write_characters(indent_string.c_str(), new_indent);
|
||||||
dump(*i, true, ensure_ascii, indent_step, new_indent);
|
dump(*i, true, ensure_ascii, indent_step, new_indent);
|
||||||
@@ -227,8 +221,7 @@ class serializer
|
|||||||
o->write_character('[');
|
o->write_character('[');
|
||||||
|
|
||||||
// first n-1 elements
|
// first n-1 elements
|
||||||
for (auto i = val.m_data.m_value.array->cbegin();
|
for (auto i = val.m_data.m_value.array->cbegin(); i != val.m_data.m_value.array->cend() - 1; ++i)
|
||||||
i != val.m_data.m_value.array->cend() - 1; ++i)
|
|
||||||
{
|
{
|
||||||
dump(*i, false, ensure_ascii, indent_step, current_indent);
|
dump(*i, false, ensure_ascii, indent_step, current_indent);
|
||||||
o->write_character(',');
|
o->write_character(',');
|
||||||
@@ -271,8 +264,7 @@ class serializer
|
|||||||
|
|
||||||
if (!val.m_data.m_value.binary->empty())
|
if (!val.m_data.m_value.binary->empty())
|
||||||
{
|
{
|
||||||
for (auto i = val.m_data.m_value.binary->cbegin();
|
for (auto i = val.m_data.m_value.binary->cbegin(); i != val.m_data.m_value.binary->cend() - 1; ++i)
|
||||||
i != val.m_data.m_value.binary->cend() - 1; ++i)
|
|
||||||
{
|
{
|
||||||
dump_integer(*i);
|
dump_integer(*i);
|
||||||
o->write_characters(", ", 2);
|
o->write_characters(", ", 2);
|
||||||
@@ -302,8 +294,7 @@ class serializer
|
|||||||
|
|
||||||
if (!val.m_data.m_value.binary->empty())
|
if (!val.m_data.m_value.binary->empty())
|
||||||
{
|
{
|
||||||
for (auto i = val.m_data.m_value.binary->cbegin();
|
for (auto i = val.m_data.m_value.binary->cbegin(); i != val.m_data.m_value.binary->cend() - 1; ++i)
|
||||||
i != val.m_data.m_value.binary->cend() - 1; ++i)
|
|
||||||
{
|
{
|
||||||
dump_integer(*i);
|
dump_integer(*i);
|
||||||
o->write_character(',');
|
o->write_character(',');
|
||||||
@@ -368,12 +359,12 @@ class serializer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON_PRIVATE_UNLESS_TESTED:
|
JSON_PRIVATE_UNLESS_TESTED :
|
||||||
/*!
|
/*!
|
||||||
@brief dump escaped string
|
@brief dump escaped string
|
||||||
|
|
||||||
@@ -408,49 +399,49 @@ class serializer
|
|||||||
{
|
{
|
||||||
switch (codepoint)
|
switch (codepoint)
|
||||||
{
|
{
|
||||||
case 0x08: // backspace
|
case 0x08: // backspace
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = 'b';
|
string_buffer[bytes++] = 'b';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x09: // horizontal tab
|
case 0x09: // horizontal tab
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = 't';
|
string_buffer[bytes++] = 't';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0A: // newline
|
case 0x0A: // newline
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = 'n';
|
string_buffer[bytes++] = 'n';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0C: // formfeed
|
case 0x0C: // formfeed
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = 'f';
|
string_buffer[bytes++] = 'f';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x0D: // carriage return
|
case 0x0D: // carriage return
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = 'r';
|
string_buffer[bytes++] = 'r';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x22: // quotation mark
|
case 0x22: // quotation mark
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = '\"';
|
string_buffer[bytes++] = '\"';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 0x5C: // reverse solidus
|
case 0x5C: // reverse solidus
|
||||||
{
|
{
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
string_buffer[bytes++] = '\\';
|
string_buffer[bytes++] = '\\';
|
||||||
@@ -466,14 +457,15 @@ class serializer
|
|||||||
if (codepoint <= 0xFFFF)
|
if (codepoint <= 0xFFFF)
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x", static_cast<std::uint16_t>(codepoint)));
|
||||||
static_cast<std::uint16_t>(codepoint)));
|
|
||||||
bytes += 6;
|
bytes += 6;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
// NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
|
static_cast<void>((std::snprintf)(string_buffer.data() + bytes,
|
||||||
|
13,
|
||||||
|
"\\u%04x\\u%04x",
|
||||||
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
|
||||||
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
|
static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
|
||||||
bytes += 12;
|
bytes += 12;
|
||||||
@@ -510,7 +502,8 @@ class serializer
|
|||||||
{
|
{
|
||||||
case error_handler_t::strict:
|
case error_handler_t::strict:
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
|
JSON_THROW(
|
||||||
|
type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
case error_handler_t::ignore:
|
case error_handler_t::ignore:
|
||||||
@@ -567,8 +560,8 @@ class serializer
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -602,7 +595,8 @@ class serializer
|
|||||||
{
|
{
|
||||||
case error_handler_t::strict:
|
case error_handler_t::strict:
|
||||||
{
|
{
|
||||||
JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
|
JSON_THROW(
|
||||||
|
type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
|
||||||
}
|
}
|
||||||
|
|
||||||
case error_handler_t::ignore:
|
case error_handler_t::ignore:
|
||||||
@@ -628,8 +622,8 @@ class serializer
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -684,13 +678,13 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// templates to avoid warnings about useless casts
|
// templates to avoid warnings about useless casts
|
||||||
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
template<typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
||||||
bool is_negative_number(NumberType x)
|
bool is_negative_number(NumberType x)
|
||||||
{
|
{
|
||||||
return x < 0;
|
return x < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
|
template<typename NumberType, enable_if_t<std::is_unsigned<NumberType>::value, int> = 0>
|
||||||
bool is_negative_number(NumberType /*unused*/)
|
bool is_negative_number(NumberType /*unused*/)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@@ -705,29 +699,27 @@ class serializer
|
|||||||
@param[in] x integer number (signed or unsigned) to dump
|
@param[in] x integer number (signed or unsigned) to dump
|
||||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||||
*/
|
*/
|
||||||
template < typename NumberType, detail::enable_if_t <
|
template<typename NumberType,
|
||||||
std::is_integral<NumberType>::value ||
|
detail::enable_if_t<std::is_integral<NumberType>::value || std::is_same<NumberType, number_unsigned_t>::value ||
|
||||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
std::is_same<NumberType, number_integer_t>::value || std::is_same<NumberType, binary_char_t>::value,
|
||||||
std::is_same<NumberType, number_integer_t>::value ||
|
int> = 0>
|
||||||
std::is_same<NumberType, binary_char_t>::value,
|
|
||||||
int > = 0 >
|
|
||||||
void dump_integer(NumberType x)
|
void dump_integer(NumberType x)
|
||||||
{
|
{
|
||||||
static constexpr std::array<std::array<char, 2>, 100> digits_to_99
|
static constexpr std::array<std::array<char, 2>, 100> digits_to_99{ {
|
||||||
{
|
{ { '0', '0' } }, { { '0', '1' } }, { { '0', '2' } }, { { '0', '3' } }, { { '0', '4' } }, { { '0', '5' } }, { { '0', '6' } }, { { '0', '7' } },
|
||||||
{
|
{ { '0', '8' } }, { { '0', '9' } }, { { '1', '0' } }, { { '1', '1' } }, { { '1', '2' } }, { { '1', '3' } }, { { '1', '4' } }, { { '1', '5' } },
|
||||||
{{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
|
{ { '1', '6' } }, { { '1', '7' } }, { { '1', '8' } }, { { '1', '9' } }, { { '2', '0' } }, { { '2', '1' } }, { { '2', '2' } }, { { '2', '3' } },
|
||||||
{{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
|
{ { '2', '4' } }, { { '2', '5' } }, { { '2', '6' } }, { { '2', '7' } }, { { '2', '8' } }, { { '2', '9' } }, { { '3', '0' } }, { { '3', '1' } },
|
||||||
{{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
|
{ { '3', '2' } }, { { '3', '3' } }, { { '3', '4' } }, { { '3', '5' } }, { { '3', '6' } }, { { '3', '7' } }, { { '3', '8' } }, { { '3', '9' } },
|
||||||
{{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
|
{ { '4', '0' } }, { { '4', '1' } }, { { '4', '2' } }, { { '4', '3' } }, { { '4', '4' } }, { { '4', '5' } }, { { '4', '6' } }, { { '4', '7' } },
|
||||||
{{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
|
{ { '4', '8' } }, { { '4', '9' } }, { { '5', '0' } }, { { '5', '1' } }, { { '5', '2' } }, { { '5', '3' } }, { { '5', '4' } }, { { '5', '5' } },
|
||||||
{{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
|
{ { '5', '6' } }, { { '5', '7' } }, { { '5', '8' } }, { { '5', '9' } }, { { '6', '0' } }, { { '6', '1' } }, { { '6', '2' } }, { { '6', '3' } },
|
||||||
{{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
|
{ { '6', '4' } }, { { '6', '5' } }, { { '6', '6' } }, { { '6', '7' } }, { { '6', '8' } }, { { '6', '9' } }, { { '7', '0' } }, { { '7', '1' } },
|
||||||
{{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
|
{ { '7', '2' } }, { { '7', '3' } }, { { '7', '4' } }, { { '7', '5' } }, { { '7', '6' } }, { { '7', '7' } }, { { '7', '8' } }, { { '7', '9' } },
|
||||||
{{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
|
{ { '8', '0' } }, { { '8', '1' } }, { { '8', '2' } }, { { '8', '3' } }, { { '8', '4' } }, { { '8', '5' } }, { { '8', '6' } }, { { '8', '7' } },
|
||||||
{{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
|
{ { '8', '8' } }, { { '8', '9' } }, { { '9', '0' } }, { { '9', '1' } }, { { '9', '2' } }, { { '9', '3' } }, { { '9', '4' } }, { { '9', '5' } },
|
||||||
}
|
{ { '9', '6' } }, { { '9', '7' } }, { { '9', '8' } }, { { '9', '9' } },
|
||||||
};
|
} };
|
||||||
|
|
||||||
// special case for "0"
|
// special case for "0"
|
||||||
if (x == 0)
|
if (x == 0)
|
||||||
@@ -737,7 +729,7 @@ class serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// use a pointer to fill the buffer
|
// use a pointer to fill the buffer
|
||||||
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
|
||||||
@@ -810,9 +802,10 @@ class serializer
|
|||||||
// guaranteed to round-trip, using strtof and strtod, resp.
|
// guaranteed to round-trip, using strtof and strtod, resp.
|
||||||
//
|
//
|
||||||
// NB: The test below works if <long double> == <double>.
|
// NB: The test below works if <long double> == <double>.
|
||||||
static constexpr bool is_ieee_single_or_double
|
static constexpr bool is_ieee_single_or_double = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 &&
|
||||||
= (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
|
std::numeric_limits<number_float_t>::max_exponent == 128) ||
|
||||||
(std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
|
(std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 &&
|
||||||
|
std::numeric_limits<number_float_t>::max_exponent == 1024);
|
||||||
|
|
||||||
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
|
||||||
}
|
}
|
||||||
@@ -863,10 +856,7 @@ class serializer
|
|||||||
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
|
o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
|
||||||
|
|
||||||
// determine if we need to append ".0"
|
// determine if we need to append ".0"
|
||||||
const bool value_is_int_like =
|
const bool value_is_int_like = std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1, [](char c) {
|
||||||
std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
|
|
||||||
[](char c)
|
|
||||||
{
|
|
||||||
return c == '.' || c == 'e';
|
return c == '.' || c == 'e';
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -899,32 +889,41 @@ class serializer
|
|||||||
*/
|
*/
|
||||||
static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::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<std::uint8_t, 400> utf8d =
|
static const std::array<std::uint8_t, 400> utf8d = { {
|
||||||
{
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
{
|
0, // 00..1F
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
|
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, 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, // 20..3F
|
0, // 20..3F
|
||||||
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, // 40..5F
|
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, 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, // 60..7F
|
0, // 40..5F
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
|
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,
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
|
0, // 60..7F
|
||||||
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
|
||||||
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
|
9, // 80..9F
|
||||||
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
|
7, // A0..BF
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
|
8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||||
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
|
2, // C0..DF
|
||||||
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
|
0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3,
|
||||||
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
|
0x3, // E0..EF
|
||||||
}
|
0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8,
|
||||||
};
|
0x8, // F0..FF
|
||||||
|
0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1,
|
||||||
|
0x1, // s0..s0
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1,
|
||||||
|
1, // s1..s2
|
||||||
|
1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1, // s3..s4
|
||||||
|
1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1,
|
||||||
|
1, // s5..s6
|
||||||
|
1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||||
|
1 // s7..s8
|
||||||
|
} };
|
||||||
|
|
||||||
JSON_ASSERT(byte < utf8d.size());
|
JSON_ASSERT(byte < utf8d.size());
|
||||||
const std::uint8_t type = utf8d[byte];
|
const std::uint8_t type = utf8d[byte];
|
||||||
|
|
||||||
codep = (state != UTF8_ACCEPT)
|
codep = (state != UTF8_ACCEPT) ? (byte & 0x3fu) | (codep << 6u) : (0xFFu >> type) & (byte);
|
||||||
? (byte & 0x3fu) | (codep << 6u)
|
|
||||||
: (0xFFu >> type) & (byte);
|
|
||||||
|
|
||||||
const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
|
const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
|
||||||
JSON_ASSERT(index < utf8d.size());
|
JSON_ASSERT(index < utf8d.size());
|
||||||
@@ -939,8 +938,8 @@ class serializer
|
|||||||
*/
|
*/
|
||||||
number_unsigned_t remove_sign(number_unsigned_t x)
|
number_unsigned_t remove_sign(number_unsigned_t x)
|
||||||
{
|
{
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
return x; // LCOV_EXCL_LINE
|
return x; // LCOV_EXCL_LINE
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -954,7 +953,7 @@ class serializer
|
|||||||
*/
|
*/
|
||||||
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
inline number_unsigned_t remove_sign(number_integer_t x) noexcept
|
||||||
{
|
{
|
||||||
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
|
JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
|
||||||
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
return static_cast<number_unsigned_t>(-(x + 1)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -963,7 +962,7 @@ class serializer
|
|||||||
output_adapter_t<char> o = nullptr;
|
output_adapter_t<char> o = nullptr;
|
||||||
|
|
||||||
/// a (hopefully) large enough character buffer
|
/// a (hopefully) large enough character buffer
|
||||||
std::array<char, 64> number_buffer{{}};
|
std::array<char, 64> number_buffer{ {} };
|
||||||
|
|
||||||
/// the locale
|
/// the locale
|
||||||
const std::lconv* loc = nullptr;
|
const std::lconv* loc = nullptr;
|
||||||
@@ -973,7 +972,7 @@ class serializer
|
|||||||
const char decimal_point = '\0';
|
const char decimal_point = '\0';
|
||||||
|
|
||||||
/// string buffer
|
/// string buffer
|
||||||
std::array<char, 512> string_buffer{{}};
|
std::array<char, 512> string_buffer{ {} };
|
||||||
|
|
||||||
/// the indentation character
|
/// the indentation character
|
||||||
const char indent_char;
|
const char indent_char;
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstring> // strlen
|
#include <cstring> // strlen
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <utility> // forward
|
#include <utility> // forward
|
||||||
|
|
||||||
#include <nlohmann/detail/meta/cpp_future.hpp>
|
#include <nlohmann/detail/meta/cpp_future.hpp>
|
||||||
#include <nlohmann/detail/meta/detected.hpp>
|
#include <nlohmann/detail/meta/detected.hpp>
|
||||||
@@ -25,26 +25,26 @@ inline std::size_t concat_length()
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline std::size_t concat_length(const char* cstr, const Args& ... rest);
|
inline std::size_t concat_length(const char* cstr, const Args&... rest);
|
||||||
|
|
||||||
template<typename StringType, typename... Args>
|
template<typename StringType, typename... Args>
|
||||||
inline std::size_t concat_length(const StringType& str, const Args& ... rest);
|
inline std::size_t concat_length(const StringType& str, const Args&... rest);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
|
inline std::size_t concat_length(const char /*c*/, const Args&... rest)
|
||||||
{
|
{
|
||||||
return 1 + concat_length(rest...);
|
return 1 + concat_length(rest...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
inline std::size_t concat_length(const char* cstr, const Args& ... rest)
|
inline std::size_t concat_length(const char* cstr, const Args&... rest)
|
||||||
{
|
{
|
||||||
// cppcheck-suppress ignoredReturnValue
|
// cppcheck-suppress ignoredReturnValue
|
||||||
return ::strlen(cstr) + concat_length(rest...);
|
return ::strlen(cstr) + concat_length(rest...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename StringType, typename... Args>
|
template<typename StringType, typename... Args>
|
||||||
inline std::size_t concat_length(const StringType& str, const Args& ... rest)
|
inline std::size_t concat_length(const StringType& str, const Args&... rest)
|
||||||
{
|
{
|
||||||
return str.size() + concat_length(rest...);
|
return str.size() + concat_length(rest...);
|
||||||
}
|
}
|
||||||
@@ -54,13 +54,13 @@ inline void concat_into(OutStringType& /*out*/)
|
|||||||
{}
|
{}
|
||||||
|
|
||||||
template<typename StringType, typename Arg>
|
template<typename StringType, typename Arg>
|
||||||
using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
|
using string_can_append = decltype(std::declval<StringType&>().append(std::declval<Arg&&>()));
|
||||||
|
|
||||||
template<typename StringType, typename Arg>
|
template<typename StringType, typename Arg>
|
||||||
using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
|
using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
|
||||||
|
|
||||||
template<typename StringType, typename Arg>
|
template<typename StringType, typename Arg>
|
||||||
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
|
using string_can_append_op = decltype(std::declval<StringType&>() += std::declval<Arg&&>());
|
||||||
|
|
||||||
template<typename StringType, typename Arg>
|
template<typename StringType, typename Arg>
|
||||||
using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
|
using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
|
||||||
@@ -77,64 +77,71 @@ using string_can_append_data = decltype(std::declval<StringType&>().append(std::
|
|||||||
template<typename StringType, typename Arg>
|
template<typename StringType, typename Arg>
|
||||||
using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
|
using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
|
typename... Args,
|
||||||
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && detect_string_can_append_op<OutStringType, Arg>::value, int> = 0>
|
||||||
|
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest);
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
typename... Args,
|
||||||
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
|
||||||
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
|
detect_string_can_append_iter<OutStringType, Arg>::value,
|
||||||
|
int> = 0>
|
||||||
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
typename... Args,
|
||||||
&& !detect_string_can_append_iter<OutStringType, Arg>::value
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
|
||||||
&& detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
|
!detect_string_can_append_iter<OutStringType, Arg>::value && detect_string_can_append_data<OutStringType, Arg>::value,
|
||||||
inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
|
int> = 0>
|
||||||
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest);
|
||||||
|
|
||||||
template<typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType, typename Arg, typename... Args, enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
|
||||||
enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
|
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest)
|
||||||
inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
|
|
||||||
{
|
{
|
||||||
out.append(std::forward<Arg>(arg));
|
out.append(std::forward<Arg>(arg));
|
||||||
concat_into(out, std::forward<Args>(rest)...);
|
concat_into(out, std::forward<Args>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& detect_string_can_append_op<OutStringType, Arg>::value, int > >
|
typename... Args,
|
||||||
inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && detect_string_can_append_op<OutStringType, Arg>::value, int>>
|
||||||
|
inline void concat_into(OutStringType& out, Arg&& arg, Args&&... rest)
|
||||||
{
|
{
|
||||||
out += std::forward<Arg>(arg);
|
out += std::forward<Arg>(arg);
|
||||||
concat_into(out, std::forward<Args>(rest)...);
|
concat_into(out, std::forward<Args>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
typename... Args,
|
||||||
&& detect_string_can_append_iter<OutStringType, Arg>::value, int > >
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
|
||||||
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
|
detect_string_can_append_iter<OutStringType, Arg>::value,
|
||||||
|
int>>
|
||||||
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest)
|
||||||
{
|
{
|
||||||
out.append(arg.begin(), arg.end());
|
out.append(arg.begin(), arg.end());
|
||||||
concat_into(out, std::forward<Args>(rest)...);
|
concat_into(out, std::forward<Args>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename OutStringType, typename Arg, typename... Args,
|
template<typename OutStringType,
|
||||||
enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
|
typename Arg,
|
||||||
&& !detect_string_can_append_op<OutStringType, Arg>::value
|
typename... Args,
|
||||||
&& !detect_string_can_append_iter<OutStringType, Arg>::value
|
enable_if_t<!detect_string_can_append<OutStringType, Arg>::value && !detect_string_can_append_op<OutStringType, Arg>::value &&
|
||||||
&& detect_string_can_append_data<OutStringType, Arg>::value, int > >
|
!detect_string_can_append_iter<OutStringType, Arg>::value && detect_string_can_append_data<OutStringType, Arg>::value,
|
||||||
inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
|
int>>
|
||||||
|
inline void concat_into(OutStringType& out, const Arg& arg, Args&&... rest)
|
||||||
{
|
{
|
||||||
out.append(arg.data(), arg.size());
|
out.append(arg.data(), arg.size());
|
||||||
concat_into(out, std::forward<Args>(rest)...);
|
concat_into(out, std::forward<Args>(rest)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename OutStringType = std::string, typename... Args>
|
template<typename OutStringType = std::string, typename... Args>
|
||||||
inline OutStringType concat(Args && ... args)
|
inline OutStringType concat(Args&&... args)
|
||||||
{
|
{
|
||||||
OutStringType str;
|
OutStringType str;
|
||||||
str.reserve(concat_length(args...));
|
str.reserve(concat_length(args...));
|
||||||
|
|||||||
@@ -28,14 +28,13 @@ enforced with an assertion.**
|
|||||||
@since version 2.0.0
|
@since version 2.0.0
|
||||||
*/
|
*/
|
||||||
template<typename StringType>
|
template<typename StringType>
|
||||||
inline void replace_substring(StringType& s, const StringType& f,
|
inline void replace_substring(StringType& s, const StringType& f, const StringType& t)
|
||||||
const StringType& t)
|
|
||||||
{
|
{
|
||||||
JSON_ASSERT(!f.empty());
|
JSON_ASSERT(!f.empty());
|
||||||
for (auto pos = s.find(f); // find first occurrence of f
|
for (auto pos = s.find(f); // find first occurrence of f
|
||||||
pos != StringType::npos; // make sure f was found
|
pos != StringType::npos; // make sure f was found
|
||||||
s.replace(pos, f.size(), t), // replace with t, and
|
s.replace(pos, f.size(), t), // replace with t, and
|
||||||
pos = s.find(f, pos + t.size())) // find next occurrence of f
|
pos = s.find(f, pos + t.size())) // find next occurrence of f
|
||||||
{}
|
{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,8 +48,8 @@ inline void replace_substring(StringType& s, const StringType& f,
|
|||||||
template<typename StringType>
|
template<typename StringType>
|
||||||
inline StringType escape(StringType s)
|
inline StringType escape(StringType s)
|
||||||
{
|
{
|
||||||
replace_substring(s, StringType{"~"}, StringType{"~0"});
|
replace_substring(s, StringType{ "~" }, StringType{ "~0" });
|
||||||
replace_substring(s, StringType{"/"}, StringType{"~1"});
|
replace_substring(s, StringType{ "/" }, StringType{ "~1" });
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,8 +63,8 @@ inline StringType escape(StringType s)
|
|||||||
template<typename StringType>
|
template<typename StringType>
|
||||||
static void unescape(StringType& s)
|
static void unescape(StringType& s)
|
||||||
{
|
{
|
||||||
replace_substring(s, StringType{"~1"}, StringType{"/"});
|
replace_substring(s, StringType{ "~1" }, StringType{ "/" });
|
||||||
replace_substring(s, StringType{"~0"}, StringType{"~"});
|
replace_substring(s, StringType{ "~0" }, StringType{ "~" });
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array> // array
|
#include <array> // array
|
||||||
#include <cstddef> // size_t
|
#include <cstddef> // size_t
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
#include <compare> // partial_ordering
|
#include <compare> // partial_ordering
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
@@ -78,24 +78,29 @@ Returns an ordering that is similar to Python:
|
|||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
|
inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
|
||||||
#else
|
#else
|
||||||
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
static constexpr std::array<std::uint8_t, 9> order = {{
|
static constexpr std::array<std::uint8_t, 9> order = { {
|
||||||
0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
|
0 /* null */,
|
||||||
1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
|
3 /* object */,
|
||||||
6 /* binary */
|
4 /* array */,
|
||||||
}
|
5 /* string */,
|
||||||
};
|
1 /* boolean */,
|
||||||
|
2 /* integer */,
|
||||||
|
2 /* unsigned */,
|
||||||
|
2 /* float */,
|
||||||
|
6 /* binary */
|
||||||
|
} };
|
||||||
|
|
||||||
const auto l_index = static_cast<std::size_t>(lhs);
|
const auto l_index = static_cast<std::size_t>(lhs);
|
||||||
const auto r_index = static_cast<std::size_t>(rhs);
|
const auto r_index = static_cast<std::size_t>(rhs);
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
if (l_index < order.size() && r_index < order.size())
|
if (l_index < order.size() && r_index < order.size())
|
||||||
{
|
{
|
||||||
return order[l_index] <=> order[r_index]; // *NOPAD*
|
return order[l_index] <=> order[r_index]; // *NOPAD*
|
||||||
}
|
}
|
||||||
return std::partial_ordering::unordered;
|
return std::partial_ordering::unordered;
|
||||||
#else
|
#else
|
||||||
@@ -110,7 +115,7 @@ Returns an ordering that is similar to Python:
|
|||||||
#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
|
#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
|
||||||
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
inline bool operator<(const value_t lhs, const value_t rhs) noexcept
|
||||||
{
|
{
|
||||||
return std::is_lt(lhs <=> rhs); // *NOPAD*
|
return std::is_lt(lhs <=> rhs); // *NOPAD*
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
+532
-673
File diff suppressed because it is too large
Load Diff
@@ -9,11 +9,11 @@
|
|||||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <memory> // allocator
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/abi_macros.hpp>
|
#include <nlohmann/detail/abi_macros.hpp>
|
||||||
|
|
||||||
@@ -36,17 +36,16 @@ struct adl_serializer;
|
|||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
template<template<typename U, typename V, typename... Args> class ObjectType = std::map,
|
||||||
std::map,
|
|
||||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||||
class StringType = std::string, class BooleanType = bool,
|
class StringType = std::string,
|
||||||
|
class BooleanType = bool,
|
||||||
class NumberIntegerType = std::int64_t,
|
class NumberIntegerType = std::int64_t,
|
||||||
class NumberUnsignedType = std::uint64_t,
|
class NumberUnsignedType = std::uint64_t,
|
||||||
class NumberFloatType = double,
|
class NumberFloatType = double,
|
||||||
template<typename U> class AllocatorType = std::allocator,
|
template<typename U> class AllocatorType = std::allocator,
|
||||||
template<typename T, typename SFINAE = void> class JSONSerializer =
|
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
|
||||||
adl_serializer,
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json;
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,14 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <functional> // equal_to, less
|
#include <functional> // equal_to, less
|
||||||
#include <initializer_list> // initializer_list
|
#include <initializer_list> // initializer_list
|
||||||
#include <iterator> // input_iterator_tag, iterator_traits
|
#include <iterator> // input_iterator_tag, iterator_traits
|
||||||
#include <memory> // allocator
|
#include <memory> // allocator
|
||||||
#include <stdexcept> // for out_of_range
|
#include <stdexcept> // for out_of_range
|
||||||
#include <type_traits> // enable_if, is_convertible
|
#include <type_traits> // enable_if, is_convertible
|
||||||
#include <utility> // pair
|
#include <utility> // pair
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||||
@@ -24,9 +24,8 @@ NLOHMANN_JSON_NAMESPACE_BEGIN
|
|||||||
|
|
||||||
/// ordered_map: a minimal map-like container that preserves insertion order
|
/// ordered_map: a minimal map-like container that preserves insertion order
|
||||||
/// for use within nlohmann::basic_json<ordered_map>
|
/// for use within nlohmann::basic_json<ordered_map>
|
||||||
template <class Key, class T, class IgnoredLess = std::less<Key>,
|
template<class Key, class T, class IgnoredLess = std::less<Key>, class Allocator = std::allocator<std::pair<const Key, T>>>
|
||||||
class Allocator = std::allocator<std::pair<const Key, T>>>
|
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
|
||||||
struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
|
|
||||||
{
|
{
|
||||||
using key_type = Key;
|
using key_type = Key;
|
||||||
using mapped_type = T;
|
using mapped_type = T;
|
||||||
@@ -43,13 +42,19 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
|
|
||||||
// Explicit constructors instead of `using Container::Container`
|
// Explicit constructors instead of `using Container::Container`
|
||||||
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
// otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
|
||||||
ordered_map() noexcept(noexcept(Container())) : Container{} {}
|
ordered_map() noexcept(noexcept(Container()))
|
||||||
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
|
: Container{}
|
||||||
template <class It>
|
{}
|
||||||
|
explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc)))
|
||||||
|
: Container{ alloc }
|
||||||
|
{}
|
||||||
|
template<class It>
|
||||||
ordered_map(It first, It last, const Allocator& alloc = Allocator())
|
ordered_map(It first, It last, const Allocator& alloc = Allocator())
|
||||||
: Container{first, last, alloc} {}
|
: Container{ first, last, alloc }
|
||||||
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
|
{}
|
||||||
: Container{init, alloc} {}
|
ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator())
|
||||||
|
: Container{ init, alloc }
|
||||||
|
{}
|
||||||
|
|
||||||
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
|
std::pair<iterator, bool> emplace(const key_type& key, T&& t)
|
||||||
{
|
{
|
||||||
@@ -57,26 +62,25 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
{
|
{
|
||||||
if (m_compare(it->first, key))
|
if (m_compare(it->first, key))
|
||||||
{
|
{
|
||||||
return {it, false};
|
return { it, false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Container::emplace_back(key, std::forward<T>(t));
|
Container::emplace_back(key, std::forward<T>(t));
|
||||||
return {std::prev(this->end()), true};
|
return { std::prev(this->end()), true };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
std::pair<iterator, bool> emplace(KeyType&& key, T&& t)
|
||||||
std::pair<iterator, bool> emplace(KeyType && key, T && t)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
if (m_compare(it->first, key))
|
if (m_compare(it->first, key))
|
||||||
{
|
{
|
||||||
return {it, false};
|
return { it, false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
|
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
|
||||||
return {std::prev(this->end()), true};
|
return { std::prev(this->end()), true };
|
||||||
}
|
}
|
||||||
|
|
||||||
T& operator[](const key_type& key)
|
T& operator[](const key_type& key)
|
||||||
@@ -84,9 +88,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return emplace(key, T{}).first->second;
|
return emplace(key, T{}).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
T& operator[](KeyType&& key)
|
||||||
T & operator[](KeyType && key)
|
|
||||||
{
|
{
|
||||||
return emplace(std::forward<KeyType>(key), T{}).first->second;
|
return emplace(std::forward<KeyType>(key), T{}).first->second;
|
||||||
}
|
}
|
||||||
@@ -96,9 +99,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return at(key);
|
return at(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
const T& operator[](KeyType&& key) const
|
||||||
const T & operator[](KeyType && key) const
|
|
||||||
{
|
{
|
||||||
return at(std::forward<KeyType>(key));
|
return at(std::forward<KeyType>(key));
|
||||||
}
|
}
|
||||||
@@ -116,9 +118,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
JSON_THROW(std::out_of_range("key not found"));
|
JSON_THROW(std::out_of_range("key not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
T& at(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -144,9 +145,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
JSON_THROW(std::out_of_range("key not found"));
|
JSON_THROW(std::out_of_range("key not found"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
const T& at(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -168,8 +168,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
// Since we cannot move const Keys, re-construct them in place
|
// Since we cannot move const Keys, re-construct them in place
|
||||||
for (auto next = it; ++next != this->end(); ++it)
|
for (auto next = it; ++next != this->end(); ++it)
|
||||||
{
|
{
|
||||||
it->~value_type(); // Destroy but keep allocation
|
it->~value_type(); // Destroy but keep allocation
|
||||||
new (&*it) value_type{std::move(*next)};
|
new (&*it) value_type{ std::move(*next) };
|
||||||
}
|
}
|
||||||
Container::pop_back();
|
Container::pop_back();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -178,9 +178,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
size_type erase(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -189,8 +188,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
// Since we cannot move const Keys, re-construct them in place
|
// Since we cannot move const Keys, re-construct them in place
|
||||||
for (auto next = it; ++next != this->end(); ++it)
|
for (auto next = it; ++next != this->end(); ++it)
|
||||||
{
|
{
|
||||||
it->~value_type(); // Destroy but keep allocation
|
it->~value_type(); // Destroy but keep allocation
|
||||||
new (&*it) value_type{std::move(*next)};
|
new (&*it) value_type{ std::move(*next) };
|
||||||
}
|
}
|
||||||
Container::pop_back();
|
Container::pop_back();
|
||||||
return 1;
|
return 1;
|
||||||
@@ -236,8 +235,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
|
|
||||||
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
|
for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
|
||||||
{
|
{
|
||||||
it->~value_type(); // destroy but keep allocation
|
it->~value_type(); // destroy but keep allocation
|
||||||
new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
|
new (&*it) value_type{ std::move(*std::next(it, elements_affected)) }; // "move" next element to it
|
||||||
}
|
}
|
||||||
|
|
||||||
// [ a, b, c, d, h, i, j, h, i, j ]
|
// [ a, b, c, d, h, i, j, h, i, j ]
|
||||||
@@ -269,9 +268,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
size_type count(KeyType&& key) const // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -295,9 +293,8 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return Container::end();
|
return Container::end();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class KeyType, detail::enable_if_t<
|
template<class KeyType, detail::enable_if_t<detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
iterator find(KeyType&& key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
|
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
@@ -321,27 +318,27 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return Container::end();
|
return Container::end();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<iterator, bool> insert( value_type&& value )
|
std::pair<iterator, bool> insert(value_type&& value)
|
||||||
{
|
{
|
||||||
return emplace(value.first, std::move(value.second));
|
return emplace(value.first, std::move(value.second));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<iterator, bool> insert( const value_type& value )
|
std::pair<iterator, bool> insert(const value_type& value)
|
||||||
{
|
{
|
||||||
for (auto it = this->begin(); it != this->end(); ++it)
|
for (auto it = this->begin(); it != this->end(); ++it)
|
||||||
{
|
{
|
||||||
if (m_compare(it->first, value.first))
|
if (m_compare(it->first, value.first))
|
||||||
{
|
{
|
||||||
return {it, false};
|
return { it, false };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Container::push_back(value);
|
Container::push_back(value);
|
||||||
return {--this->end(), true};
|
return { --this->end(), true };
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename InputIt>
|
template<typename InputIt>
|
||||||
using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
|
using require_input_iter =
|
||||||
std::input_iterator_tag>::value>::type;
|
typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category, std::input_iterator_tag>::value>::type;
|
||||||
|
|
||||||
template<typename InputIt, typename = require_input_iter<InputIt>>
|
template<typename InputIt, typename = require_input_iter<InputIt>>
|
||||||
void insert(InputIt first, InputIt last)
|
void insert(InputIt first, InputIt last)
|
||||||
@@ -352,7 +349,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+1608
-1934
File diff suppressed because it is too large
Load Diff
+7856
-5130
File diff suppressed because it is too large
Load Diff
@@ -9,11 +9,11 @@
|
|||||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||||
|
|
||||||
#include <cstdint> // int64_t, uint64_t
|
#include <cstdint> // int64_t, uint64_t
|
||||||
#include <map> // map
|
#include <map> // map
|
||||||
#include <memory> // allocator
|
#include <memory> // allocator
|
||||||
#include <string> // string
|
#include <string> // string
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
// #include <nlohmann/detail/abi_macros.hpp>
|
// #include <nlohmann/detail/abi_macros.hpp>
|
||||||
// __ _____ _____ _____
|
// __ _____ _____ _____
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// This file contains all macro definitions affecting or depending on the ABI
|
// This file contains all macro definitions affecting or depending on the ABI
|
||||||
|
|
||||||
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
||||||
@@ -65,59 +63,44 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Construct the namespace ABI tags component
|
// Construct the namespace ABI tags component
|
||||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi##a##b
|
||||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
|
||||||
|
|
||||||
#define NLOHMANN_JSON_ABI_TAGS \
|
#define NLOHMANN_JSON_ABI_TAGS NLOHMANN_JSON_ABI_TAGS_CONCAT(NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
|
||||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
|
||||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
|
||||||
|
|
||||||
// Construct the namespace version component
|
// Construct the namespace version component
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) _v##major##_##minor##_##patch
|
||||||
_v ## major ## _ ## minor ## _ ## patch
|
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
|
||||||
|
|
||||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||||
#else
|
#else
|
||||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, NLOHMANN_JSON_VERSION_MINOR, NLOHMANN_JSON_VERSION_PATCH)
|
||||||
NLOHMANN_JSON_VERSION_MINOR, \
|
|
||||||
NLOHMANN_JSON_VERSION_PATCH)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Combine namespace components
|
// Combine namespace components
|
||||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a##b
|
||||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||||
#define NLOHMANN_JSON_NAMESPACE \
|
#define NLOHMANN_JSON_NAMESPACE nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
|
||||||
NLOHMANN_JSON_ABI_TAGS, \
|
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||||
namespace nlohmann \
|
namespace nlohmann \
|
||||||
{ \
|
{ \
|
||||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT(NLOHMANN_JSON_ABI_TAGS, NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||||
NLOHMANN_JSON_ABI_TAGS, \
|
{
|
||||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
|
||||||
{
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||||
} // namespace nlohmann
|
} // namespace nlohmann
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief namespace for Niels Lohmann
|
@brief namespace for Niels Lohmann
|
||||||
@see https://github.com/nlohmann
|
@see https://github.com/nlohmann
|
||||||
@@ -137,17 +120,16 @@ struct adl_serializer;
|
|||||||
|
|
||||||
/// a class to store JSON values
|
/// a class to store JSON values
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
template<template<typename U, typename V, typename... Args> class ObjectType = std::map,
|
||||||
std::map,
|
|
||||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||||
class StringType = std::string, class BooleanType = bool,
|
class StringType = std::string,
|
||||||
|
class BooleanType = bool,
|
||||||
class NumberIntegerType = std::int64_t,
|
class NumberIntegerType = std::int64_t,
|
||||||
class NumberUnsignedType = std::uint64_t,
|
class NumberUnsignedType = std::uint64_t,
|
||||||
class NumberFloatType = double,
|
class NumberFloatType = double,
|
||||||
template<typename U> class AllocatorType = std::allocator,
|
template<typename U> class AllocatorType = std::allocator,
|
||||||
template<typename T, typename SFINAE = void> class JSONSerializer =
|
template<typename T, typename SFINAE = void> class JSONSerializer = adl_serializer,
|
||||||
adl_serializer,
|
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
||||||
class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
|
|
||||||
class CustomBaseClass = void>
|
class CustomBaseClass = void>
|
||||||
class basic_json;
|
class basic_json;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#define STRINGIZE(x) STRINGIZE_EX(x)
|
#define STRINGIZE(x) STRINGIZE_EX(x)
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
|
std::string namespace_name(std::string ns, T* /*unused*/ = nullptr) // NOLINT(performance-unnecessary-value-param)
|
||||||
{
|
{
|
||||||
#if DOCTEST_MSVC && !DOCTEST_CLANG
|
#if DOCTEST_MSVC && !DOCTEST_CLANG
|
||||||
ns = __FUNCSIG__;
|
ns = __FUNCSIG__;
|
||||||
|
|||||||
@@ -11,8 +11,10 @@
|
|||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
|
|
||||||
// define custom namespace
|
// define custom namespace
|
||||||
#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
|
#define NLOHMANN_JSON_NAMESPACE nlohmann // this line may be omitted
|
||||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN namespace nlohmann {
|
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||||
|
namespace nlohmann \
|
||||||
|
{
|
||||||
#define NLOHMANN_JSON_NAMESPACE_END }
|
#define NLOHMANN_JSON_NAMESPACE_END }
|
||||||
#include <nlohmann/json_fwd.hpp>
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
@@ -25,7 +27,7 @@ TEST_CASE("custom namespace")
|
|||||||
std::string expected = "nlohmann::basic_json";
|
std::string expected = "nlohmann::basic_json";
|
||||||
|
|
||||||
// fallback for Clang
|
// fallback for Clang
|
||||||
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
|
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
|
||||||
|
|
||||||
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,20 +20,20 @@ TEST_CASE("default namespace")
|
|||||||
{
|
{
|
||||||
std::string expected = "nlohmann::json_abi";
|
std::string expected = "nlohmann::json_abi";
|
||||||
|
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
expected += "_diag";
|
expected += "_diag";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||||
expected += "_ldvcmp";
|
expected += "_ldvcmp";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
|
expected += "_v" STRINGIZE(NLOHMANN_JSON_VERSION_MAJOR);
|
||||||
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
|
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_MINOR);
|
||||||
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
|
expected += "_" STRINGIZE(NLOHMANN_JSON_VERSION_PATCH) "::basic_json";
|
||||||
|
|
||||||
// fallback for Clang
|
// fallback for Clang
|
||||||
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
|
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
|
||||||
|
|
||||||
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,18 +21,18 @@ TEST_CASE("default namespace without version component")
|
|||||||
{
|
{
|
||||||
std::string expected = "nlohmann::json_abi";
|
std::string expected = "nlohmann::json_abi";
|
||||||
|
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
expected += "_diag";
|
expected += "_diag";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||||
expected += "_ldvcmp";
|
expected += "_ldvcmp";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
expected += "::basic_json";
|
expected += "::basic_json";
|
||||||
|
|
||||||
// fallback for Clang
|
// fallback for Clang
|
||||||
const std::string ns{STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json"};
|
const std::string ns{ STRINGIZE(NLOHMANN_JSON_NAMESPACE) "::basic_json" };
|
||||||
|
|
||||||
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
CHECK(namespace_name<nlohmann::json>(ns) == expected);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ std::size_t json_sizeof_diag_off_explicit()
|
|||||||
void json_at_diag_off()
|
void json_at_diag_off()
|
||||||
{
|
{
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
json j = json{{"foo", json::object()}};
|
json j = json{ { "foo", json::object() } };
|
||||||
j.at(json::json_pointer("/foo/bar"));
|
j.at(json::json_pointer("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,6 @@ std::size_t json_sizeof_diag_on_explicit()
|
|||||||
void json_at_diag_on()
|
void json_at_diag_on()
|
||||||
{
|
{
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
json j = json{{"foo", json::object()}};
|
json j = json{ { "foo", json::object() } };
|
||||||
j.at(json::json_pointer("/foo/bar"));
|
j.at(json::json_pointer("/foo/bar"));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@
|
|||||||
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#include <benchmark/benchmark.h>
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include <vector>
|
|
||||||
#include <test_data.hpp>
|
#include <test_data.hpp>
|
||||||
|
#include <vector>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <benchmark/benchmark.h>
|
||||||
|
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
@@ -39,13 +39,13 @@ static void ParseFile(benchmark::State& state, const char* filename)
|
|||||||
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
std::ifstream file(filename, std::ios::binary | std::ios::ate);
|
||||||
state.SetBytesProcessed(state.iterations() * file.tellg());
|
state.SetBytesProcessed(state.iterations() * file.tellg());
|
||||||
}
|
}
|
||||||
BENCHMARK_CAPTURE(ParseFile, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
BENCHMARK_CAPTURE(ParseFile, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
BENCHMARK_CAPTURE(ParseFile, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
BENCHMARK_CAPTURE(ParseFile, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
BENCHMARK_CAPTURE(ParseFile, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
BENCHMARK_CAPTURE(ParseFile, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
BENCHMARK_CAPTURE(ParseFile, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
BENCHMARK_CAPTURE(ParseFile, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
||||||
BENCHMARK_CAPTURE(ParseFile, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
BENCHMARK_CAPTURE(ParseFile, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -72,13 +72,13 @@ static void ParseString(benchmark::State& state, const char* filename)
|
|||||||
|
|
||||||
state.SetBytesProcessed(state.iterations() * str.size());
|
state.SetBytesProcessed(state.iterations() * str.size());
|
||||||
}
|
}
|
||||||
BENCHMARK_CAPTURE(ParseString, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
BENCHMARK_CAPTURE(ParseString, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
BENCHMARK_CAPTURE(ParseString, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
BENCHMARK_CAPTURE(ParseString, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
BENCHMARK_CAPTURE(ParseString, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
BENCHMARK_CAPTURE(ParseString, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
BENCHMARK_CAPTURE(ParseString, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
BENCHMARK_CAPTURE(ParseString, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
||||||
BENCHMARK_CAPTURE(ParseString, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
BENCHMARK_CAPTURE(ParseString, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -98,22 +98,22 @@ static void Dump(benchmark::State& state, const char* filename, int indent)
|
|||||||
|
|
||||||
state.SetBytesProcessed(state.iterations() * j.dump(indent).size());
|
state.SetBytesProcessed(state.iterations() * j.dump(indent).size());
|
||||||
}
|
}
|
||||||
BENCHMARK_CAPTURE(Dump, jeopardy / -, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", -1);
|
BENCHMARK_CAPTURE(Dump, jeopardy / -, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, jeopardy / 4, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", 4);
|
BENCHMARK_CAPTURE(Dump, jeopardy / 4, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, canada / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", -1);
|
BENCHMARK_CAPTURE(Dump, canada / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, canada / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", 4);
|
BENCHMARK_CAPTURE(Dump, canada / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, citm_catalog / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", -1);
|
BENCHMARK_CAPTURE(Dump, citm_catalog / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
|
BENCHMARK_CAPTURE(Dump, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, twitter / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", -1);
|
BENCHMARK_CAPTURE(Dump, twitter / -, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
|
BENCHMARK_CAPTURE(Dump, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, floats / -, TEST_DATA_DIRECTORY "/regression/floats.json", -1);
|
BENCHMARK_CAPTURE(Dump, floats / -, TEST_DATA_DIRECTORY "/regression/floats.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, floats / 4, TEST_DATA_DIRECTORY "/regression/floats.json", 4);
|
BENCHMARK_CAPTURE(Dump, floats / 4, TEST_DATA_DIRECTORY "/regression/floats.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, signed_ints / -, TEST_DATA_DIRECTORY "/regression/signed_ints.json", -1);
|
BENCHMARK_CAPTURE(Dump, signed_ints / -, TEST_DATA_DIRECTORY "/regression/signed_ints.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, signed_ints / 4, TEST_DATA_DIRECTORY "/regression/signed_ints.json", 4);
|
BENCHMARK_CAPTURE(Dump, signed_ints / 4, TEST_DATA_DIRECTORY "/regression/signed_ints.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, unsigned_ints / -, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", -1);
|
BENCHMARK_CAPTURE(Dump, unsigned_ints / -, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, unsigned_ints / 4, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 4);
|
BENCHMARK_CAPTURE(Dump, unsigned_ints / 4, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json", 4);
|
||||||
BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", -1);
|
BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", -1);
|
||||||
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
|
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// serialize CBOR
|
// serialize CBOR
|
||||||
@@ -131,13 +131,13 @@ static void ToCbor(benchmark::State& state, const char* filename)
|
|||||||
|
|
||||||
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
|
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
|
||||||
}
|
}
|
||||||
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
||||||
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -162,8 +162,8 @@ static void BinaryToCbor(benchmark::State& state)
|
|||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
json::binary_t bin{in};
|
json::binary_t bin{ in };
|
||||||
json j{{"type", "binary"}, {"data", bin}};
|
json j{ { "type", "binary" }, { "data", bin } };
|
||||||
|
|
||||||
while (state.KeepRunning())
|
while (state.KeepRunning())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
|
||||||
#include "Foo.hpp"
|
#include "Foo.hpp"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
class Bar : public Foo {};
|
class Bar : public Foo
|
||||||
|
{};
|
||||||
|
|||||||
@@ -9,4 +9,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
class Foo {};
|
class Foo
|
||||||
|
{};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
int main()
|
int main()
|
||||||
{
|
{
|
||||||
nlohmann::ordered_json json = {"Test"};
|
nlohmann::ordered_json json = { "Test" };
|
||||||
json.dump();
|
json.dump();
|
||||||
|
|
||||||
// regression for #3013 (ordered_json::reset() compile error with nvcc)
|
// regression for #3013 (ordered_json::reset() compile error with nvcc)
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ an implementation of the `LLVMFuzzerTestOneInput` function which processes a
|
|||||||
passed byte array.
|
passed byte array.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <vector> // for vector
|
|
||||||
#include <cstdint> // for uint8_t
|
#include <cstdint> // for uint8_t
|
||||||
#include <iostream> // for cin
|
#include <iostream> // for cin
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size);
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,10 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdio> // fopen, fclose, FILE
|
#include <cstdio> // fopen, fclose, FILE
|
||||||
#include <memory> // unique_ptr
|
|
||||||
#include <test_data.hpp>
|
|
||||||
#include <doctest.h>
|
#include <doctest.h>
|
||||||
|
#include <memory> // unique_ptr
|
||||||
|
#include <test_data.hpp>
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
{
|
{
|
||||||
@@ -24,7 +24,10 @@ inline bool check_testsuite_downloaded()
|
|||||||
|
|
||||||
TEST_CASE("check test suite is downloaded")
|
TEST_CASE("check test suite is downloaded")
|
||||||
{
|
{
|
||||||
REQUIRE_MESSAGE(utils::check_testsuite_downloaded(), "Test data not found in '" TEST_DATA_DIRECTORY "'. Please execute target 'download_test_data' before running this test suite. See <https://github.com/nlohmann/json#execute-unit-tests> for more information.");
|
REQUIRE_MESSAGE(
|
||||||
|
utils::check_testsuite_downloaded(),
|
||||||
|
"Test data not found in '" TEST_DATA_DIRECTORY
|
||||||
|
"'. Please execute target 'download_test_data' before running this test suite. See <https://github.com/nlohmann/json#execute-unit-tests> for more information.");
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t
|
||||||
#include <fstream> // ifstream, istreambuf_iterator, ios
|
#include <fstream> // ifstream, istreambuf_iterator, ios
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
namespace utils
|
namespace utils
|
||||||
{
|
{
|
||||||
@@ -30,4 +30,4 @@ inline std::vector<std::uint8_t> read_binary_file(const std::string& filename)
|
|||||||
return byte_vector;
|
return byte_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace utils
|
} // namespace utils
|
||||||
|
|||||||
+23
-15
@@ -11,10 +11,10 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
#include <climits> // SIZE_MAX
|
#include <climits> // SIZE_MAX
|
||||||
#include <limits> // numeric_limits
|
#include <limits> // numeric_limits
|
||||||
|
|
||||||
template <typename OfType, typename T, bool MinInRange, bool MaxInRange>
|
template<typename OfType, typename T, bool MinInRange, bool MaxInRange>
|
||||||
struct trait_test_arg
|
struct trait_test_arg
|
||||||
{
|
{
|
||||||
using of_type = OfType;
|
using of_type = OfType;
|
||||||
@@ -92,10 +92,10 @@ TEST_CASE("32bit")
|
|||||||
REQUIRE(SIZE_MAX == 0xffffffff);
|
REQUIRE(SIZE_MAX == 0xffffffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \
|
TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test,
|
||||||
trait_test_arg<std::size_t, std::int32_t, false, true>, \
|
trait_test_arg<std::size_t, std::int32_t, false, true>,
|
||||||
trait_test_arg<std::size_t, std::uint32_t, true, true>, \
|
trait_test_arg<std::size_t, std::uint32_t, true, true>,
|
||||||
trait_test_arg<std::size_t, std::int64_t, false, false>, \
|
trait_test_arg<std::size_t, std::int64_t, false, false>,
|
||||||
trait_test_arg<std::size_t, std::uint64_t, true, false>);
|
trait_test_arg<std::size_t, std::uint64_t, true, false>);
|
||||||
|
|
||||||
TEST_CASE("BJData")
|
TEST_CASE("BJData")
|
||||||
@@ -106,27 +106,35 @@ TEST_CASE("BJData")
|
|||||||
{
|
{
|
||||||
SECTION("optimized array: negative size")
|
SECTION("optimized array: negative size")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
|
std::vector<uint8_t> const vM = { '[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']' };
|
||||||
std::vector<uint8_t> const vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'};
|
std::vector<uint8_t> const vMX = { '[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']' };
|
||||||
|
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM),
|
||||||
|
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
|
||||||
|
json::out_of_range&);
|
||||||
CHECK(json::from_bjdata(vM, true, false).is_discarded());
|
CHECK(json::from_bjdata(vM, true, false).is_discarded());
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX),
|
||||||
|
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
|
||||||
|
json::out_of_range&);
|
||||||
CHECK(json::from_bjdata(vMX, true, false).is_discarded());
|
CHECK(json::from_bjdata(vMX, true, false).is_discarded());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("optimized array: integer value overflow")
|
SECTION("optimized array: integer value overflow")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> const vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F};
|
std::vector<uint8_t> const vL = { '[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F };
|
||||||
std::vector<uint8_t> const vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'};
|
std::vector<uint8_t> const vM = { '[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']' };
|
||||||
|
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL),
|
||||||
|
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
|
||||||
|
json::out_of_range&);
|
||||||
CHECK(json::from_bjdata(vL, true, false).is_discarded());
|
CHECK(json::from_bjdata(vL, true, false).is_discarded());
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM),
|
||||||
|
"[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow",
|
||||||
|
json::out_of_range&);
|
||||||
CHECK(json::from_bjdata(vM, true, false).is_discarded());
|
CHECK(json::from_bjdata(vM, true, false).is_discarded());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,43 +14,37 @@ using nlohmann::json;
|
|||||||
|
|
||||||
TEST_CASE("algorithms")
|
TEST_CASE("algorithms")
|
||||||
{
|
{
|
||||||
json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
|
json j_array = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz" };
|
||||||
json j_object = {{"one", 1}, {"two", 2}};
|
json j_object = { { "one", 1 }, { "two", 2 } };
|
||||||
|
|
||||||
SECTION("non-modifying sequence operations")
|
SECTION("non-modifying sequence operations")
|
||||||
{
|
{
|
||||||
SECTION("std::all_of")
|
SECTION("std::all_of")
|
||||||
{
|
{
|
||||||
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
|
CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return !value.empty();
|
return !value.empty();
|
||||||
}));
|
}));
|
||||||
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
|
CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return value.type() == json::value_t::number_integer;
|
return value.type() == json::value_t::number_integer;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::any_of")
|
SECTION("std::any_of")
|
||||||
{
|
{
|
||||||
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
|
CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return value.is_string() && value.get<std::string>() == "foo";
|
return value.is_string() && value.get<std::string>() == "foo";
|
||||||
}));
|
}));
|
||||||
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
|
CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return value.get<int>() > 1;
|
return value.get<int>() > 1;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::none_of")
|
SECTION("std::none_of")
|
||||||
{
|
{
|
||||||
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
|
CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return value.empty();
|
return value.empty();
|
||||||
}));
|
}));
|
||||||
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
|
CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json& value) {
|
||||||
{
|
|
||||||
return value.get<int>() <= 0;
|
return value.get<int>() <= 0;
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -61,8 +55,7 @@ TEST_CASE("algorithms")
|
|||||||
{
|
{
|
||||||
int sum = 0;
|
int sum = 0;
|
||||||
|
|
||||||
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
|
std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json& value) {
|
||||||
{
|
|
||||||
if (value.is_number())
|
if (value.is_number())
|
||||||
{
|
{
|
||||||
sum += static_cast<int>(value);
|
sum += static_cast<int>(value);
|
||||||
@@ -74,8 +67,7 @@ TEST_CASE("algorithms")
|
|||||||
|
|
||||||
SECTION("writing")
|
SECTION("writing")
|
||||||
{
|
{
|
||||||
auto add17 = [](json & value)
|
auto add17 = [](json& value) {
|
||||||
{
|
|
||||||
if (value.is_array())
|
if (value.is_array())
|
||||||
{
|
{
|
||||||
value.push_back(17);
|
value.push_back(17);
|
||||||
@@ -84,7 +76,7 @@ TEST_CASE("algorithms")
|
|||||||
|
|
||||||
std::for_each(j_array.begin(), j_array.end(), add17);
|
std::for_each(j_array.begin(), j_array.end(), add17);
|
||||||
|
|
||||||
CHECK(j_array[6] == json({1, 2, 3, 17}));
|
CHECK(j_array[6] == json({ 1, 2, 3, 17 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,22 +87,20 @@ TEST_CASE("algorithms")
|
|||||||
|
|
||||||
SECTION("std::count_if")
|
SECTION("std::count_if")
|
||||||
{
|
{
|
||||||
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
|
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
{
|
return (value.is_number());
|
||||||
return (value.is_number());
|
}) == 3);
|
||||||
}) == 3);
|
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&) {
|
||||||
CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
|
return true;
|
||||||
{
|
}) == 9);
|
||||||
return true;
|
|
||||||
}) == 9);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::mismatch")
|
SECTION("std::mismatch")
|
||||||
{
|
{
|
||||||
json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
|
json j_array2 = { 13, 29, 3, { { "one", 1 }, { "two", 2 }, { "three", 3 } }, true, false, { 1, 2, 3 }, "foo", "baz" };
|
||||||
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
|
auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
|
||||||
CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
|
CHECK(*res.first == json({ { "one", 1 }, { "two", 2 } }));
|
||||||
CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
|
CHECK(*res.second == json({ { "one", 1 }, { "two", 2 }, { "three", 3 } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::equal")
|
SECTION("std::equal")
|
||||||
@@ -125,11 +115,9 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("using user-defined comparison")
|
SECTION("using user-defined comparison")
|
||||||
{
|
{
|
||||||
// compare objects only by size of its elements
|
// compare objects only by size of its elements
|
||||||
json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
|
json j_array2 = { 13, 29, 3, { "Hello", "World" }, true, false, { { "one", 1 }, { "two", 2 }, { "three", 3 } }, "foo", "baz" };
|
||||||
CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
|
CHECK(!std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
|
||||||
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
|
CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(), [](const json& a, const json& b) {
|
||||||
[](const json & a, const json & b)
|
|
||||||
{
|
|
||||||
return (a.size() == b.size());
|
return (a.size() == b.size());
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
@@ -143,9 +131,7 @@ TEST_CASE("algorithms")
|
|||||||
|
|
||||||
SECTION("std::find_if")
|
SECTION("std::find_if")
|
||||||
{
|
{
|
||||||
auto it = std::find_if(j_array.begin(), j_array.end(),
|
auto it = std::find_if(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
[](const json & value)
|
|
||||||
{
|
|
||||||
return value.is_boolean();
|
return value.is_boolean();
|
||||||
});
|
});
|
||||||
CHECK(std::distance(j_array.begin(), it) == 4);
|
CHECK(std::distance(j_array.begin(), it) == 4);
|
||||||
@@ -153,9 +139,7 @@ TEST_CASE("algorithms")
|
|||||||
|
|
||||||
SECTION("std::find_if_not")
|
SECTION("std::find_if_not")
|
||||||
{
|
{
|
||||||
auto it = std::find_if_not(j_array.begin(), j_array.end(),
|
auto it = std::find_if_not(j_array.begin(), j_array.end(), [](const json& value) {
|
||||||
[](const json & value)
|
|
||||||
{
|
|
||||||
return value.is_number();
|
return value.is_number();
|
||||||
});
|
});
|
||||||
CHECK(std::distance(j_array.begin(), it) == 3);
|
CHECK(std::distance(j_array.begin(), it) == 3);
|
||||||
@@ -164,11 +148,9 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("std::adjacent_find")
|
SECTION("std::adjacent_find")
|
||||||
{
|
{
|
||||||
CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
|
CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
|
||||||
CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
|
CHECK(std::adjacent_find(j_array.begin(), j_array.end(), [](const json& v1, const json& v2) {
|
||||||
[](const json & v1, const json & v2)
|
return v1.type() == v2.type();
|
||||||
{
|
}) == j_array.begin());
|
||||||
return v1.type() == v2.type();
|
|
||||||
}) == j_array.begin());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,19 +159,18 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("std::reverse")
|
SECTION("std::reverse")
|
||||||
{
|
{
|
||||||
std::reverse(j_array.begin(), j_array.end());
|
std::reverse(j_array.begin(), j_array.end());
|
||||||
CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
|
CHECK(j_array == json({ "baz", "foo", { 1, 2, 3 }, false, true, { { "one", 1 }, { "two", 2 } }, 3, 29, 13 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::rotate")
|
SECTION("std::rotate")
|
||||||
{
|
{
|
||||||
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
|
std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
|
||||||
CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
|
CHECK(j_array == json({ 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", 13 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::partition")
|
SECTION("std::partition")
|
||||||
{
|
{
|
||||||
auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
|
auto it = std::partition(j_array.begin(), j_array.end(), [](const json& v) {
|
||||||
{
|
|
||||||
return v.is_string();
|
return v.is_string();
|
||||||
});
|
});
|
||||||
CHECK(std::distance(j_array.begin(), it) == 2);
|
CHECK(std::distance(j_array.begin(), it) == 2);
|
||||||
@@ -203,33 +184,34 @@ TEST_CASE("algorithms")
|
|||||||
{
|
{
|
||||||
SECTION("with standard comparison")
|
SECTION("with standard comparison")
|
||||||
{
|
{
|
||||||
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
|
json j = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", nullptr };
|
||||||
std::sort(j.begin(), j.end());
|
std::sort(j.begin(), j.end());
|
||||||
CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
|
CHECK(j == json({ nullptr, false, true, 3, 13, 29, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, "baz", "foo" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with user-defined comparison")
|
SECTION("with user-defined comparison")
|
||||||
{
|
{
|
||||||
json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
|
json j = { 3, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, nullptr };
|
||||||
std::sort(j.begin(), j.end(), [](const json & a, const json & b)
|
std::sort(j.begin(), j.end(), [](const json& a, const json& b) {
|
||||||
{
|
|
||||||
return a.size() < b.size();
|
return a.size() < b.size();
|
||||||
});
|
});
|
||||||
CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
|
CHECK(j == json({ nullptr, 3, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("sorting an object")
|
SECTION("sorting an object")
|
||||||
{
|
{
|
||||||
json j({{"one", 1}, {"two", 2}});
|
json j({ { "one", 1 }, { "two", 2 } });
|
||||||
CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()), "[json.exception.invalid_iterator.209] cannot use offsets with object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(std::sort(j.begin(), j.end()),
|
||||||
|
"[json.exception.invalid_iterator.209] cannot use offsets with object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::partial_sort")
|
SECTION("std::partial_sort")
|
||||||
{
|
{
|
||||||
json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
|
json j = { 13, 29, 3, { { "one", 1 }, { "two", 2 } }, true, false, { 1, 2, 3 }, "foo", "baz", nullptr };
|
||||||
std::partial_sort(j.begin(), j.begin() + 4, j.end());
|
std::partial_sort(j.begin(), j.begin() + 4, j.end());
|
||||||
CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
|
CHECK(j == json({ nullptr, false, true, 3, { { "one", 1 }, { "two", 2 } }, 29, { 1, 2, 3 }, "foo", "baz", 13 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -238,53 +220,53 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("std::merge")
|
SECTION("std::merge")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j1 = {2, 4, 6, 8};
|
json j1 = { 2, 4, 6, 8 };
|
||||||
json j2 = {1, 2, 3, 5, 7};
|
json j2 = { 1, 2, 3, 5, 7 };
|
||||||
json j3;
|
json j3;
|
||||||
|
|
||||||
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||||
CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
|
CHECK(j3 == json({ 1, 2, 2, 3, 4, 5, 6, 7, 8 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::set_difference")
|
SECTION("std::set_difference")
|
||||||
{
|
{
|
||||||
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
|
json j1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||||
json j2 = {1, 2, 3, 5, 7};
|
json j2 = { 1, 2, 3, 5, 7 };
|
||||||
json j3;
|
json j3;
|
||||||
|
|
||||||
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||||
CHECK(j3 == json({4, 6, 8}));
|
CHECK(j3 == json({ 4, 6, 8 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::set_intersection")
|
SECTION("std::set_intersection")
|
||||||
{
|
{
|
||||||
json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
|
json j1 = { 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||||
json j2 = {1, 2, 3, 5, 7};
|
json j2 = { 1, 2, 3, 5, 7 };
|
||||||
json j3;
|
json j3;
|
||||||
|
|
||||||
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||||
CHECK(j3 == json({1, 2, 3, 5, 7}));
|
CHECK(j3 == json({ 1, 2, 3, 5, 7 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::set_union")
|
SECTION("std::set_union")
|
||||||
{
|
{
|
||||||
json j1 = {2, 4, 6, 8};
|
json j1 = { 2, 4, 6, 8 };
|
||||||
json j2 = {1, 2, 3, 5, 7};
|
json j2 = { 1, 2, 3, 5, 7 };
|
||||||
json j3;
|
json j3;
|
||||||
|
|
||||||
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||||
CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
|
CHECK(j3 == json({ 1, 2, 3, 4, 5, 6, 7, 8 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("std::set_symmetric_difference")
|
SECTION("std::set_symmetric_difference")
|
||||||
{
|
{
|
||||||
json j1 = {2, 4, 6, 8};
|
json j1 = { 2, 4, 6, 8 };
|
||||||
json j2 = {1, 2, 3, 5, 7};
|
json j2 = { 1, 2, 3, 5, 7 };
|
||||||
json j3;
|
json j3;
|
||||||
|
|
||||||
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
|
||||||
CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
|
CHECK(j3 == json({ 1, 3, 4, 5, 6, 7, 8 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -293,29 +275,29 @@ TEST_CASE("algorithms")
|
|||||||
std::make_heap(j_array.begin(), j_array.end());
|
std::make_heap(j_array.begin(), j_array.end());
|
||||||
CHECK(std::is_heap(j_array.begin(), j_array.end()));
|
CHECK(std::is_heap(j_array.begin(), j_array.end()));
|
||||||
std::sort_heap(j_array.begin(), j_array.end());
|
std::sort_heap(j_array.begin(), j_array.end());
|
||||||
CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
|
CHECK(j_array == json({ false, true, 3, 13, 29, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3 }, "baz", "foo" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("iota")
|
SECTION("iota")
|
||||||
{
|
{
|
||||||
SECTION("int")
|
SECTION("int")
|
||||||
{
|
{
|
||||||
json json_arr = {0, 5, 2, 4, 10, 20, 30, 40, 50, 1};
|
json json_arr = { 0, 5, 2, 4, 10, 20, 30, 40, 50, 1 };
|
||||||
std::iota(json_arr.begin(), json_arr.end(), 0);
|
std::iota(json_arr.begin(), json_arr.end(), 0);
|
||||||
CHECK(json_arr == json({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));
|
CHECK(json_arr == json({ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }));
|
||||||
}
|
}
|
||||||
SECTION("double")
|
SECTION("double")
|
||||||
{
|
{
|
||||||
json json_arr = {0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5};
|
json json_arr = { 0.5, 1.5, 1.3, 4.1, 10.2, 20.5, 30.6, 40.1, 50.22, 1.5 };
|
||||||
std::iota(json_arr.begin(), json_arr.end(), 0.5);
|
std::iota(json_arr.begin(), json_arr.end(), 0.5);
|
||||||
CHECK(json_arr == json({0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5}));
|
CHECK(json_arr == json({ 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, 8.5, 9.5 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("char")
|
SECTION("char")
|
||||||
{
|
{
|
||||||
json json_arr = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1'};
|
json json_arr = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', '0', '1' };
|
||||||
std::iota(json_arr.begin(), json_arr.end(), '0');
|
std::iota(json_arr.begin(), json_arr.end(), '0');
|
||||||
CHECK(json_arr == json({'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}));
|
CHECK(json_arr == json({ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +306,7 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("copy without if")
|
SECTION("copy without if")
|
||||||
{
|
{
|
||||||
json dest_arr;
|
json dest_arr;
|
||||||
const json source_arr = {1, 2, 3, 4};
|
const json source_arr = { 1, 2, 3, 4 };
|
||||||
|
|
||||||
std::copy(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr));
|
std::copy(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr));
|
||||||
|
|
||||||
@@ -333,33 +315,30 @@ TEST_CASE("algorithms")
|
|||||||
SECTION("copy if")
|
SECTION("copy if")
|
||||||
{
|
{
|
||||||
json dest_arr;
|
json dest_arr;
|
||||||
const json source_arr = {0, 3, 6, 9, 12, 15, 20};
|
const json source_arr = { 0, 3, 6, 9, 12, 15, 20 };
|
||||||
|
|
||||||
std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json & _value)
|
std::copy_if(source_arr.begin(), source_arr.end(), std::back_inserter(dest_arr), [](const json& _value) {
|
||||||
{
|
|
||||||
return _value.get<int>() % 3 == 0;
|
return _value.get<int>() % 3 == 0;
|
||||||
});
|
});
|
||||||
CHECK(dest_arr == json({0, 3, 6, 9, 12, 15}));
|
CHECK(dest_arr == json({ 0, 3, 6, 9, 12, 15 }));
|
||||||
}
|
}
|
||||||
SECTION("copy n")
|
SECTION("copy n")
|
||||||
{
|
{
|
||||||
const json source_arr = {0, 1, 2, 3, 4, 5, 6, 7};
|
const json source_arr = { 0, 1, 2, 3, 4, 5, 6, 7 };
|
||||||
json dest_arr;
|
json dest_arr;
|
||||||
const unsigned char numToCopy = 2;
|
const unsigned char numToCopy = 2;
|
||||||
|
|
||||||
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
|
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
|
||||||
CHECK(dest_arr == json{0, 1});
|
CHECK(dest_arr == json{ 0, 1 });
|
||||||
|
|
||||||
}
|
}
|
||||||
SECTION("copy n chars")
|
SECTION("copy n chars")
|
||||||
{
|
{
|
||||||
const json source_arr = {'1', '2', '3', '4', '5', '6', '7'};
|
const json source_arr = { '1', '2', '3', '4', '5', '6', '7' };
|
||||||
json dest_arr;
|
json dest_arr;
|
||||||
const unsigned char numToCopy = 4;
|
const unsigned char numToCopy = 4;
|
||||||
|
|
||||||
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
|
std::copy_n(source_arr.begin(), numToCopy, std::back_inserter(dest_arr));
|
||||||
CHECK(dest_arr == json{'1', '2', '3', '4'});
|
CHECK(dest_arr == json{ '1', '2', '3', '4' });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,35 +21,30 @@ struct bad_allocator : std::allocator<T>
|
|||||||
using std::allocator<T>::allocator;
|
using std::allocator<T>::allocator;
|
||||||
|
|
||||||
bad_allocator() = default;
|
bad_allocator() = default;
|
||||||
template<class U> bad_allocator(const bad_allocator<U>& /*unused*/) { }
|
template<class U>
|
||||||
|
bad_allocator(const bad_allocator<U>& /*unused*/)
|
||||||
|
{}
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
void construct(T* /*unused*/, Args&& ... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
|
void construct(T* /*unused*/, Args&&... /*unused*/) // NOLINT(cppcoreguidelines-missing-std-forward)
|
||||||
{
|
{
|
||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template<class U>
|
||||||
struct rebind
|
struct rebind
|
||||||
{
|
{
|
||||||
using other = bad_allocator<U>;
|
using other = bad_allocator<U>;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("bad_alloc")
|
TEST_CASE("bad_alloc")
|
||||||
{
|
{
|
||||||
SECTION("bad_alloc")
|
SECTION("bad_alloc")
|
||||||
{
|
{
|
||||||
// create JSON type using the throwing allocator
|
// create JSON type using the throwing allocator
|
||||||
using bad_json = nlohmann::basic_json<std::map,
|
using bad_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, bad_allocator>;
|
||||||
std::vector,
|
|
||||||
std::string,
|
|
||||||
bool,
|
|
||||||
std::int64_t,
|
|
||||||
std::uint64_t,
|
|
||||||
double,
|
|
||||||
bad_allocator>;
|
|
||||||
|
|
||||||
// creating an object should throw
|
// creating an object should throw
|
||||||
CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&);
|
CHECK_THROWS_AS(bad_json(bad_json::value_t::object), std::bad_alloc&);
|
||||||
@@ -68,7 +63,7 @@ struct my_allocator : std::allocator<T>
|
|||||||
using std::allocator<T>::allocator;
|
using std::allocator<T>::allocator;
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
void construct(T* p, Args&& ... args)
|
void construct(T* p, Args&&... args)
|
||||||
{
|
{
|
||||||
if (next_construct_fails)
|
if (next_construct_fails)
|
||||||
{
|
{
|
||||||
@@ -98,11 +93,11 @@ struct my_allocator : std::allocator<T>
|
|||||||
throw std::bad_alloc();
|
throw std::bad_alloc();
|
||||||
}
|
}
|
||||||
|
|
||||||
static_cast<void>(p); // fix MSVC's C4100 warning
|
static_cast<void>(p); // fix MSVC's C4100 warning
|
||||||
p->~T();
|
p->~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class U>
|
template<class U>
|
||||||
struct rebind
|
struct rebind
|
||||||
{
|
{
|
||||||
using other = my_allocator<U>;
|
using other = my_allocator<U>;
|
||||||
@@ -118,19 +113,12 @@ void my_allocator_clean_up(T* p)
|
|||||||
alloc.destroy(p);
|
alloc.destroy(p);
|
||||||
alloc.deallocate(p, 1);
|
alloc.deallocate(p, 1);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("controlled bad_alloc")
|
TEST_CASE("controlled bad_alloc")
|
||||||
{
|
{
|
||||||
// create JSON type using the throwing allocator
|
// create JSON type using the throwing allocator
|
||||||
using my_json = nlohmann::basic_json<std::map,
|
using my_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, my_allocator>;
|
||||||
std::vector,
|
|
||||||
std::string,
|
|
||||||
bool,
|
|
||||||
std::int64_t,
|
|
||||||
std::uint64_t,
|
|
||||||
double,
|
|
||||||
my_allocator>;
|
|
||||||
|
|
||||||
SECTION("class json_value")
|
SECTION("class json_value")
|
||||||
{
|
{
|
||||||
@@ -181,7 +169,7 @@ TEST_CASE("controlled bad_alloc")
|
|||||||
SECTION("basic_json(const CompatibleObjectType&)")
|
SECTION("basic_json(const CompatibleObjectType&)")
|
||||||
{
|
{
|
||||||
next_construct_fails = false;
|
next_construct_fails = false;
|
||||||
const std::map<std::string, std::string> v {{"foo", "bar"}};
|
const std::map<std::string, std::string> v{ { "foo", "bar" } };
|
||||||
CHECK_NOTHROW(my_json(v));
|
CHECK_NOTHROW(my_json(v));
|
||||||
next_construct_fails = true;
|
next_construct_fails = true;
|
||||||
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
|
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
|
||||||
@@ -191,7 +179,7 @@ TEST_CASE("controlled bad_alloc")
|
|||||||
SECTION("basic_json(const CompatibleArrayType&)")
|
SECTION("basic_json(const CompatibleArrayType&)")
|
||||||
{
|
{
|
||||||
next_construct_fails = false;
|
next_construct_fails = false;
|
||||||
const std::vector<std::string> v {"foo", "bar", "baz"};
|
const std::vector<std::string> v{ "foo", "bar", "baz" };
|
||||||
CHECK_NOTHROW(my_json(v));
|
CHECK_NOTHROW(my_json(v));
|
||||||
next_construct_fails = true;
|
next_construct_fails = true;
|
||||||
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
|
CHECK_THROWS_AS(my_json(v), std::bad_alloc&);
|
||||||
@@ -225,36 +213,30 @@ template<class T>
|
|||||||
struct allocator_no_forward : std::allocator<T>
|
struct allocator_no_forward : std::allocator<T>
|
||||||
{
|
{
|
||||||
allocator_no_forward() = default;
|
allocator_no_forward() = default;
|
||||||
template <class U>
|
template<class U>
|
||||||
allocator_no_forward(allocator_no_forward<U> /*unused*/) {}
|
allocator_no_forward(allocator_no_forward<U> /*unused*/)
|
||||||
|
{}
|
||||||
|
|
||||||
template <class U>
|
template<class U>
|
||||||
struct rebind
|
struct rebind
|
||||||
{
|
{
|
||||||
using other = allocator_no_forward<U>;
|
using other = allocator_no_forward<U>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <class... Args>
|
template<class... Args>
|
||||||
void construct(T* p, const Args& ... args) noexcept(noexcept(::new (static_cast<void*>(p)) T(args...)))
|
void construct(T* p, const Args&... args) noexcept(noexcept(::new(static_cast<void*>(p)) T(args...)))
|
||||||
{
|
{
|
||||||
// force copy even if move is available
|
// force copy even if move is available
|
||||||
::new (static_cast<void*>(p)) T(args...);
|
::new (static_cast<void*>(p)) T(args...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("bad my_allocator::construct")
|
TEST_CASE("bad my_allocator::construct")
|
||||||
{
|
{
|
||||||
SECTION("my_allocator::construct doesn't forward")
|
SECTION("my_allocator::construct doesn't forward")
|
||||||
{
|
{
|
||||||
using bad_alloc_json = nlohmann::basic_json<std::map,
|
using bad_alloc_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int64_t, std::uint64_t, double, allocator_no_forward>;
|
||||||
std::vector,
|
|
||||||
std::string,
|
|
||||||
bool,
|
|
||||||
std::int64_t,
|
|
||||||
std::uint64_t,
|
|
||||||
double,
|
|
||||||
allocator_no_forward>;
|
|
||||||
|
|
||||||
bad_alloc_json j;
|
bad_alloc_json j;
|
||||||
j["test"] = bad_alloc_json::array_t();
|
j["test"] = bad_alloc_json::array_t();
|
||||||
|
|||||||
@@ -30,13 +30,19 @@ class alt_string
|
|||||||
|
|
||||||
static constexpr auto npos = static_cast<std::size_t>(-1);
|
static constexpr auto npos = static_cast<std::size_t>(-1);
|
||||||
|
|
||||||
alt_string(const char* str): str_impl(str) {}
|
alt_string(const char* str)
|
||||||
alt_string(const char* str, std::size_t count): str_impl(str, count) {}
|
: str_impl(str)
|
||||||
alt_string(size_t count, char chr): str_impl(count, chr) {}
|
{}
|
||||||
|
alt_string(const char* str, std::size_t count)
|
||||||
|
: str_impl(str, count)
|
||||||
|
{}
|
||||||
|
alt_string(size_t count, char chr)
|
||||||
|
: str_impl(count, chr)
|
||||||
|
{}
|
||||||
alt_string() = default;
|
alt_string() = default;
|
||||||
|
|
||||||
template <typename...TParams>
|
template<typename... TParams>
|
||||||
alt_string& append(TParams&& ...params)
|
alt_string& append(TParams&&... params)
|
||||||
{
|
{
|
||||||
str_impl.append(std::forward<TParams>(params)...);
|
str_impl.append(std::forward<TParams>(params)...);
|
||||||
return *this;
|
return *this;
|
||||||
@@ -47,7 +53,7 @@ class alt_string
|
|||||||
str_impl.push_back(c);
|
str_impl.push_back(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename op_type>
|
template<typename op_type>
|
||||||
bool operator==(const op_type& op) const
|
bool operator==(const op_type& op) const
|
||||||
{
|
{
|
||||||
return str_impl == op;
|
return str_impl == op;
|
||||||
@@ -58,7 +64,7 @@ class alt_string
|
|||||||
return str_impl == op.str_impl;
|
return str_impl == op.str_impl;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename op_type>
|
template<typename op_type>
|
||||||
bool operator!=(const op_type& op) const
|
bool operator!=(const op_type& op) const
|
||||||
{
|
{
|
||||||
return str_impl != op;
|
return str_impl != op;
|
||||||
@@ -74,17 +80,17 @@ class alt_string
|
|||||||
return str_impl.size();
|
return str_impl.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize (std::size_t n)
|
void resize(std::size_t n)
|
||||||
{
|
{
|
||||||
str_impl.resize(n);
|
str_impl.resize(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize (std::size_t n, char c)
|
void resize(std::size_t n, char c)
|
||||||
{
|
{
|
||||||
str_impl.resize(n, c);
|
str_impl.resize(n, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename op_type>
|
template<typename op_type>
|
||||||
bool operator<(const op_type& op) const noexcept
|
bool operator<(const op_type& op) const noexcept
|
||||||
{
|
{
|
||||||
return str_impl < op;
|
return str_impl < op;
|
||||||
@@ -148,7 +154,7 @@ class alt_string
|
|||||||
alt_string substr(std::size_t pos = 0, std::size_t count = npos) const
|
alt_string substr(std::size_t pos = 0, std::size_t count = npos) const
|
||||||
{
|
{
|
||||||
const std::string s = str_impl.substr(pos, count);
|
const std::string s = str_impl.substr(pos, count);
|
||||||
return {s.data(), s.size()};
|
return { s.data(), s.size() };
|
||||||
}
|
}
|
||||||
|
|
||||||
alt_string& replace(std::size_t pos, std::size_t count, const alt_string& str)
|
alt_string& replace(std::size_t pos, std::size_t count, const alt_string& str)
|
||||||
@@ -158,7 +164,7 @@ class alt_string
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string str_impl {};
|
std::string str_impl{};
|
||||||
|
|
||||||
friend bool operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept;
|
friend bool operator<(const char* /*op1*/, const alt_string& /*op2*/) noexcept;
|
||||||
};
|
};
|
||||||
@@ -168,16 +174,7 @@ void int_to_string(alt_string& target, std::size_t value)
|
|||||||
target = std::to_string(value).c_str();
|
target = std::to_string(value).c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
using alt_json = nlohmann::basic_json <
|
using alt_json = nlohmann::basic_json<std::map, std::vector, alt_string, bool, std::int64_t, std::uint64_t, double, std::allocator, nlohmann::adl_serializer>;
|
||||||
std::map,
|
|
||||||
std::vector,
|
|
||||||
alt_string,
|
|
||||||
bool,
|
|
||||||
std::int64_t,
|
|
||||||
std::uint64_t,
|
|
||||||
double,
|
|
||||||
std::allocator,
|
|
||||||
nlohmann::adl_serializer >;
|
|
||||||
|
|
||||||
bool operator<(const char* op1, const alt_string& op2) noexcept
|
bool operator<(const char* op1, const alt_string& op2) noexcept
|
||||||
{
|
{
|
||||||
@@ -232,7 +229,7 @@ TEST_CASE("alternative string type")
|
|||||||
|
|
||||||
{
|
{
|
||||||
alt_json doc;
|
alt_json doc;
|
||||||
doc["object"] = { {"currency", "USD"}, {"value", 42.99} };
|
doc["object"] = { { "currency", "USD" }, { "value", 42.99 } };
|
||||||
alt_string dump = doc.dump();
|
alt_string dump = doc.dump();
|
||||||
CHECK(dump == R"({"object":{"currency":"USD","value":42.99}})");
|
CHECK(dump == R"({"object":{"currency":"USD","value":42.99}})");
|
||||||
}
|
}
|
||||||
@@ -259,11 +256,11 @@ TEST_CASE("alternative string type")
|
|||||||
|
|
||||||
for (const auto& item : doc_array.items())
|
for (const auto& item : doc_array.items())
|
||||||
{
|
{
|
||||||
if (item.key() == "0" )
|
if (item.key() == "0")
|
||||||
{
|
{
|
||||||
CHECK( item.value() == "foo" );
|
CHECK(item.value() == "foo");
|
||||||
}
|
}
|
||||||
else if (item.key() == "1" )
|
else if (item.key() == "1")
|
||||||
{
|
{
|
||||||
CHECK(item.value() == "bar");
|
CHECK(item.value() == "bar");
|
||||||
}
|
}
|
||||||
@@ -280,14 +277,14 @@ TEST_CASE("alternative string type")
|
|||||||
doc["Who are you?"] = "I'm Batman";
|
doc["Who are you?"] = "I'm Batman";
|
||||||
|
|
||||||
CHECK("I'm Batman" == doc["Who are you?"]);
|
CHECK("I'm Batman" == doc["Who are you?"]);
|
||||||
CHECK(doc["Who are you?"] == "I'm Batman");
|
CHECK(doc["Who are you?"] == "I'm Batman");
|
||||||
CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
|
CHECK_FALSE("I'm Batman" != doc["Who are you?"]);
|
||||||
CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
|
CHECK_FALSE(doc["Who are you?"] != "I'm Batman");
|
||||||
|
|
||||||
CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
|
CHECK("I'm Bruce Wayne" != doc["Who are you?"]);
|
||||||
CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
|
CHECK(doc["Who are you?"] != "I'm Bruce Wayne");
|
||||||
CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
|
CHECK_FALSE("I'm Bruce Wayne" == doc["Who are you?"]);
|
||||||
CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
|
CHECK_FALSE(doc["Who are you?"] == "I'm Bruce Wayne");
|
||||||
|
|
||||||
{
|
{
|
||||||
const alt_json& const_doc = doc;
|
const alt_json& const_doc = doc;
|
||||||
|
|||||||
@@ -18,7 +18,11 @@ DOCTEST_CLANG_SUPPRESS_WARNING("-Wstrict-overflow")
|
|||||||
static int assert_counter;
|
static int assert_counter;
|
||||||
|
|
||||||
/// set failure variable to true instead of calling assert(x)
|
/// set failure variable to true instead of calling assert(x)
|
||||||
#define JSON_ASSERT(x) {if (!(x)) ++assert_counter; }
|
#define JSON_ASSERT(x) \
|
||||||
|
{ \
|
||||||
|
if (!(x)) \
|
||||||
|
++assert_counter; \
|
||||||
|
}
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include "make_test_data_available.hpp"
|
#include "make_test_data_available.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
TEST_CASE("Binary Formats" * doctest::skip())
|
TEST_CASE("Binary Formats" * doctest::skip())
|
||||||
{
|
{
|
||||||
@@ -142,7 +142,7 @@ TEST_CASE("Binary Formats" * doctest::skip())
|
|||||||
const auto bjdata_1_size = json::to_bjdata(j).size();
|
const auto bjdata_1_size = json::to_bjdata(j).size();
|
||||||
const auto bjdata_2_size = json::to_bjdata(j, true).size();
|
const auto bjdata_2_size = json::to_bjdata(j, true).size();
|
||||||
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
|
const auto bjdata_3_size = json::to_bjdata(j, true, true).size();
|
||||||
const auto bson_size = json::to_bson({{"", j}}).size(); // wrap array in object for BSON
|
const auto bson_size = json::to_bson({ { "", j } }).size(); // wrap array in object for BSON
|
||||||
const auto cbor_size = json::to_cbor(j).size();
|
const auto cbor_size = json::to_cbor(j).size();
|
||||||
const auto msgpack_size = json::to_msgpack(j).size();
|
const auto msgpack_size = json::to_msgpack(j).size();
|
||||||
const auto ubjson_1_size = json::to_ubjson(j).size();
|
const auto ubjson_1_size = json::to_ubjson(j).size();
|
||||||
|
|||||||
+999
-892
File diff suppressed because it is too large
Load Diff
+562
-443
File diff suppressed because it is too large
Load Diff
@@ -45,7 +45,7 @@ TEST_CASE("byte_container_with_subtype")
|
|||||||
|
|
||||||
SECTION("comparisons")
|
SECTION("comparisons")
|
||||||
{
|
{
|
||||||
std::vector<std::uint8_t> const bytes = {{0xCA, 0xFE, 0xBA, 0xBE}};
|
std::vector<std::uint8_t> const bytes = { { 0xCA, 0xFE, 0xBA, 0xBE } };
|
||||||
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container1;
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container1;
|
||||||
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container2({}, 42);
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container2({}, 42);
|
||||||
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container3(bytes);
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container3(bytes);
|
||||||
|
|||||||
+36
-36
@@ -18,7 +18,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
{
|
{
|
||||||
json j = true; // NOLINT(misc-const-correctness)
|
json j = true; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = true;
|
const json j_const = true;
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -36,7 +36,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json j = "hello world"; // NOLINT(misc-const-correctness)
|
json j = "hello world"; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = "hello world";
|
const json j_const = "hello world";
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -56,7 +56,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty array")
|
SECTION("empty array")
|
||||||
{
|
{
|
||||||
json j = json::array(); // NOLINT(misc-const-correctness)
|
json j = json::array(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::array();
|
const json j_const = json::array();
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -74,8 +74,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled array")
|
SECTION("filled array")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
|
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {1, 2, 3};
|
const json j_const = { 1, 2, 3 };
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
{
|
{
|
||||||
@@ -95,7 +95,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty object")
|
SECTION("empty object")
|
||||||
{
|
{
|
||||||
json j = json::object(); // NOLINT(misc-const-correctness)
|
json j = json::object(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::object();
|
const json j_const = json::object();
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -113,8 +113,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled object")
|
SECTION("filled object")
|
||||||
{
|
{
|
||||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
|
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
|
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
{
|
{
|
||||||
@@ -132,7 +132,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
{
|
{
|
||||||
json j = -23; // NOLINT(misc-const-correctness)
|
json j = -23; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = -23;
|
const json j_const = -23;
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -150,7 +150,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (unsigned)")
|
SECTION("number (unsigned)")
|
||||||
{
|
{
|
||||||
json j = 23u; // NOLINT(misc-const-correctness)
|
json j = 23u; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23u;
|
const json j_const = 23u;
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -168,7 +168,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (float)")
|
SECTION("number (float)")
|
||||||
{
|
{
|
||||||
json j = 23.42; // NOLINT(misc-const-correctness)
|
json j = 23.42; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23.42;
|
const json j_const = 23.42;
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -186,7 +186,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
json j = nullptr; // NOLINT(misc-const-correctness)
|
json j = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = nullptr;
|
const json j_const = nullptr;
|
||||||
|
|
||||||
SECTION("result of empty")
|
SECTION("result of empty")
|
||||||
@@ -207,7 +207,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
{
|
{
|
||||||
json j = true; // NOLINT(misc-const-correctness)
|
json j = true; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = true;
|
const json j_const = true;
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -227,7 +227,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json j = "hello world"; // NOLINT(misc-const-correctness)
|
json j = "hello world"; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = "hello world";
|
const json j_const = "hello world";
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -249,7 +249,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty array")
|
SECTION("empty array")
|
||||||
{
|
{
|
||||||
json j = json::array(); // NOLINT(misc-const-correctness)
|
json j = json::array(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::array();
|
const json j_const = json::array();
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -269,8 +269,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled array")
|
SECTION("filled array")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
|
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {1, 2, 3};
|
const json j_const = { 1, 2, 3 };
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
{
|
{
|
||||||
@@ -292,7 +292,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty object")
|
SECTION("empty object")
|
||||||
{
|
{
|
||||||
json j = json::object(); // NOLINT(misc-const-correctness)
|
json j = json::object(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::object();
|
const json j_const = json::object();
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -312,8 +312,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled object")
|
SECTION("filled object")
|
||||||
{
|
{
|
||||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
|
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
|
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
{
|
{
|
||||||
@@ -333,7 +333,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
{
|
{
|
||||||
json j = -23; // NOLINT(misc-const-correctness)
|
json j = -23; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = -23;
|
const json j_const = -23;
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -353,7 +353,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (unsigned)")
|
SECTION("number (unsigned)")
|
||||||
{
|
{
|
||||||
json j = 23u; // NOLINT(misc-const-correctness)
|
json j = 23u; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23u;
|
const json j_const = 23u;
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -373,7 +373,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (float)")
|
SECTION("number (float)")
|
||||||
{
|
{
|
||||||
json j = 23.42; // NOLINT(misc-const-correctness)
|
json j = 23.42; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23.42;
|
const json j_const = 23.42;
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -393,7 +393,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
json j = nullptr; // NOLINT(misc-const-correctness)
|
json j = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = nullptr;
|
const json j_const = nullptr;
|
||||||
|
|
||||||
SECTION("result of size")
|
SECTION("result of size")
|
||||||
@@ -416,7 +416,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
{
|
{
|
||||||
json j = true; // NOLINT(misc-const-correctness)
|
json j = true; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = true;
|
const json j_const = true;
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -428,7 +428,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json j = "hello world"; // NOLINT(misc-const-correctness)
|
json j = "hello world"; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = "hello world";
|
const json j_const = "hello world";
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -442,7 +442,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty array")
|
SECTION("empty array")
|
||||||
{
|
{
|
||||||
json j = json::array(); // NOLINT(misc-const-correctness)
|
json j = json::array(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::array();
|
const json j_const = json::array();
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -454,8 +454,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled array")
|
SECTION("filled array")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3}; // NOLINT(misc-const-correctness)
|
json j = { 1, 2, 3 }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {1, 2, 3};
|
const json j_const = { 1, 2, 3 };
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
{
|
{
|
||||||
@@ -469,7 +469,7 @@ TEST_CASE("capacity")
|
|||||||
{
|
{
|
||||||
SECTION("empty object")
|
SECTION("empty object")
|
||||||
{
|
{
|
||||||
json j = json::object(); // NOLINT(misc-const-correctness)
|
json j = json::object(); // NOLINT(misc-const-correctness)
|
||||||
const json j_const = json::object();
|
const json j_const = json::object();
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -481,8 +481,8 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("filled object")
|
SECTION("filled object")
|
||||||
{
|
{
|
||||||
json j = {{"one", 1}, {"two", 2}, {"three", 3}}; // NOLINT(misc-const-correctness)
|
json j = { { "one", 1 }, { "two", 2 }, { "three", 3 } }; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = {{"one", 1}, {"two", 2}, {"three", 3}};
|
const json j_const = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
{
|
{
|
||||||
@@ -494,7 +494,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
{
|
{
|
||||||
json j = -23; // NOLINT(misc-const-correctness)
|
json j = -23; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = -23;
|
const json j_const = -23;
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -506,7 +506,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (unsigned)")
|
SECTION("number (unsigned)")
|
||||||
{
|
{
|
||||||
json j = 23u; // NOLINT(misc-const-correctness)
|
json j = 23u; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23u;
|
const json j_const = 23u;
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -518,7 +518,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("number (float)")
|
SECTION("number (float)")
|
||||||
{
|
{
|
||||||
json j = 23.42; // NOLINT(misc-const-correctness)
|
json j = 23.42; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = 23.42;
|
const json j_const = 23.42;
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
@@ -530,7 +530,7 @@ TEST_CASE("capacity")
|
|||||||
|
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
json j = nullptr; // NOLINT(misc-const-correctness)
|
json j = nullptr; // NOLINT(misc-const-correctness)
|
||||||
const json j_const = nullptr;
|
const json j_const = nullptr;
|
||||||
|
|
||||||
SECTION("result of max_size")
|
SECTION("result of max_size")
|
||||||
|
|||||||
+784
-686
File diff suppressed because it is too large
Load Diff
@@ -49,7 +49,7 @@ TEST_CASE("const_iterator class")
|
|||||||
{
|
{
|
||||||
SECTION("create from uninitialized iterator")
|
SECTION("create from uninitialized iterator")
|
||||||
{
|
{
|
||||||
const json::iterator it {};
|
const json::iterator it{};
|
||||||
json::const_iterator const cit(it);
|
json::const_iterator const cit(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,14 +141,14 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator const it = j.cbegin();
|
json::const_iterator const it = j.cbegin();
|
||||||
CHECK(*it == json("bar"));
|
CHECK(*it == json("bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator const it = j.cbegin();
|
json::const_iterator const it = j.cbegin();
|
||||||
CHECK(*it == json(1));
|
CHECK(*it == json(1));
|
||||||
}
|
}
|
||||||
@@ -174,14 +174,14 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator const it = j.cbegin();
|
json::const_iterator const it = j.cbegin();
|
||||||
CHECK(std::string(it->type_name()) == "string");
|
CHECK(std::string(it->type_name()) == "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator const it = j.cbegin();
|
json::const_iterator const it = j.cbegin();
|
||||||
CHECK(std::string(it->type_name()) == "number");
|
CHECK(std::string(it->type_name()) == "number");
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator it = j.cbegin();
|
json::const_iterator it = j.cbegin();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
||||||
it++;
|
it++;
|
||||||
@@ -223,7 +223,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator it = j.cbegin();
|
json::const_iterator it = j.cbegin();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
||||||
it++;
|
it++;
|
||||||
@@ -265,7 +265,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator it = j.cbegin();
|
json::const_iterator it = j.cbegin();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
||||||
++it;
|
++it;
|
||||||
@@ -274,7 +274,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator it = j.cbegin();
|
json::const_iterator it = j.cbegin();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
||||||
++it;
|
++it;
|
||||||
@@ -314,7 +314,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator it = j.cend();
|
json::const_iterator it = j.cend();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
||||||
it--;
|
it--;
|
||||||
@@ -323,7 +323,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator it = j.cend();
|
json::const_iterator it = j.cend();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
||||||
it--;
|
it--;
|
||||||
@@ -363,7 +363,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j({{"foo", "bar"}});
|
json const j({ { "foo", "bar" } });
|
||||||
json::const_iterator it = j.cend();
|
json::const_iterator it = j.cend();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
||||||
--it;
|
--it;
|
||||||
@@ -372,7 +372,7 @@ TEST_CASE("const_iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j({1, 2, 3, 4});
|
json const j({ 1, 2, 3, 4 });
|
||||||
json::const_iterator it = j.cend();
|
json::const_iterator it = j.cend();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
||||||
--it;
|
--it;
|
||||||
|
|||||||
@@ -131,14 +131,14 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator const it = j.begin();
|
json::iterator const it = j.begin();
|
||||||
CHECK(*it == json("bar"));
|
CHECK(*it == json("bar"));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator const it = j.begin();
|
json::iterator const it = j.begin();
|
||||||
CHECK(*it == json(1));
|
CHECK(*it == json(1));
|
||||||
}
|
}
|
||||||
@@ -164,14 +164,14 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator const it = j.begin();
|
json::iterator const it = j.begin();
|
||||||
CHECK(std::string(it->type_name()) == "string");
|
CHECK(std::string(it->type_name()) == "string");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator const it = j.begin();
|
json::iterator const it = j.begin();
|
||||||
CHECK(std::string(it->type_name()) == "number");
|
CHECK(std::string(it->type_name()) == "number");
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator it = j.begin();
|
json::iterator it = j.begin();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
||||||
it++;
|
it++;
|
||||||
@@ -213,7 +213,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator it = j.begin();
|
json::iterator it = j.begin();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
||||||
it++;
|
it++;
|
||||||
@@ -255,7 +255,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator it = j.begin();
|
json::iterator it = j.begin();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->begin()));
|
||||||
++it;
|
++it;
|
||||||
@@ -264,7 +264,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator it = j.begin();
|
json::iterator it = j.begin();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->begin()));
|
||||||
++it;
|
++it;
|
||||||
@@ -304,7 +304,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator it = j.end();
|
json::iterator it = j.end();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
||||||
it--;
|
it--;
|
||||||
@@ -313,7 +313,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator it = j.end();
|
json::iterator it = j.end();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
||||||
it--;
|
it--;
|
||||||
@@ -353,7 +353,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j({{"foo", "bar"}});
|
json j({ { "foo", "bar" } });
|
||||||
json::iterator it = j.end();
|
json::iterator it = j.end();
|
||||||
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
CHECK((it.m_it.object_iterator == it.m_object->m_data.m_value.object->end()));
|
||||||
--it;
|
--it;
|
||||||
@@ -362,7 +362,7 @@ TEST_CASE("iterator class")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j({1, 2, 3, 4});
|
json j({ 1, 2, 3, 4 });
|
||||||
json::iterator it = j.end();
|
json::iterator it = j.end();
|
||||||
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
CHECK((it.m_it.array_iterator == it.m_object->m_data.m_value.array->end()));
|
||||||
--it;
|
--it;
|
||||||
@@ -387,18 +387,18 @@ TEST_CASE("iterator class")
|
|||||||
SECTION("primitive_iterator_t")
|
SECTION("primitive_iterator_t")
|
||||||
{
|
{
|
||||||
using Iter = nlohmann::detail::primitive_iterator_t;
|
using Iter = nlohmann::detail::primitive_iterator_t;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
|
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
|
||||||
}
|
}
|
||||||
SECTION("iter_impl")
|
SECTION("iter_impl")
|
||||||
{
|
{
|
||||||
using Iter = nlohmann::detail::iter_impl<json>;
|
using Iter = nlohmann::detail::iter_impl<json>;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
|
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
|
||||||
}
|
}
|
||||||
SECTION("json_reverse_iterator")
|
SECTION("json_reverse_iterator")
|
||||||
{
|
{
|
||||||
using Base = nlohmann::detail::iter_impl<json>;
|
using Base = nlohmann::detail::iter_impl<json>;
|
||||||
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()++), Iter >::value);
|
CHECK(std::is_same<decltype(std::declval<Iter&>()++), Iter>::value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SECTION("post-decrement")
|
SECTION("post-decrement")
|
||||||
@@ -406,18 +406,18 @@ TEST_CASE("iterator class")
|
|||||||
SECTION("primitive_iterator_t")
|
SECTION("primitive_iterator_t")
|
||||||
{
|
{
|
||||||
using Iter = nlohmann::detail::primitive_iterator_t;
|
using Iter = nlohmann::detail::primitive_iterator_t;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value);
|
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
|
||||||
}
|
}
|
||||||
SECTION("iter_impl")
|
SECTION("iter_impl")
|
||||||
{
|
{
|
||||||
using Iter = nlohmann::detail::iter_impl<json>;
|
using Iter = nlohmann::detail::iter_impl<json>;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
|
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
|
||||||
}
|
}
|
||||||
SECTION("json_reverse_iterator")
|
SECTION("json_reverse_iterator")
|
||||||
{
|
{
|
||||||
using Base = nlohmann::detail::iter_impl<json>;
|
using Base = nlohmann::detail::iter_impl<json>;
|
||||||
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
||||||
CHECK(std::is_same < decltype(std::declval<Iter&>()--), Iter >::value );
|
CHECK(std::is_same<decltype(std::declval<Iter&>()--), Iter>::value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -462,7 +462,6 @@ TEST_CASE("iterator class")
|
|||||||
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
using Iter = nlohmann::detail::json_reverse_iterator<Base>;
|
||||||
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
|
CHECK_FALSE(is_detected<can_post_decrement_temporary, Iter&>::value);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,15 +19,15 @@ json::lexer::token_type scan_string(const char* s, bool ignore_comments = false)
|
|||||||
json::lexer::token_type scan_string(const char* s, const bool ignore_comments)
|
json::lexer::token_type scan_string(const char* s, const bool ignore_comments)
|
||||||
{
|
{
|
||||||
auto ia = nlohmann::detail::input_adapter(s);
|
auto ia = nlohmann::detail::input_adapter(s);
|
||||||
return nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments).scan(); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
return nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments).scan(); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::string get_error_message(const char* s, bool ignore_comments = false);
|
std::string get_error_message(const char* s, bool ignore_comments = false);
|
||||||
std::string get_error_message(const char* s, const bool ignore_comments)
|
std::string get_error_message(const char* s, const bool ignore_comments)
|
||||||
{
|
{
|
||||||
auto ia = nlohmann::detail::input_adapter(s);
|
auto ia = nlohmann::detail::input_adapter(s);
|
||||||
auto lexer = nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
auto lexer = nlohmann::detail::lexer<json, decltype(ia)>(std::move(ia), ignore_comments); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
|
||||||
lexer.scan();
|
lexer.scan();
|
||||||
return lexer.get_error_message();
|
return lexer.get_error_message();
|
||||||
}
|
}
|
||||||
|
|||||||
+525
-256
File diff suppressed because it is too large
Load Diff
+174
-181
@@ -23,7 +23,8 @@ using nlohmann::json;
|
|||||||
// this can be replaced with the doctest stl extension header in version 2.5
|
// this can be replaced with the doctest stl extension header in version 2.5
|
||||||
namespace doctest
|
namespace doctest
|
||||||
{
|
{
|
||||||
template<> struct StringMaker<std::partial_ordering>
|
template<>
|
||||||
|
struct StringMaker<std::partial_ordering>
|
||||||
{
|
{
|
||||||
static String convert(const std::partial_ordering& order)
|
static String convert(const std::partial_ordering& order)
|
||||||
{
|
{
|
||||||
@@ -46,7 +47,7 @@ template<> struct StringMaker<std::partial_ordering>
|
|||||||
return "{?}";
|
return "{?}";
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // namespace doctest
|
} // namespace doctest
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -54,12 +55,12 @@ namespace
|
|||||||
{
|
{
|
||||||
// helper function to check std::less<json::value_t>
|
// helper function to check std::less<json::value_t>
|
||||||
// see https://en.cppreference.com/w/cpp/utility/functional/less
|
// see https://en.cppreference.com/w/cpp/utility/functional/less
|
||||||
template <typename A, typename B, typename U = std::less<json::value_t>>
|
template<typename A, typename B, typename U = std::less<json::value_t>>
|
||||||
bool f(A a, B b, U u = U())
|
bool f(A a, B b, U u = U())
|
||||||
{
|
{
|
||||||
return u(a, b);
|
return u(a, b);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("lexicographical comparison operators")
|
TEST_CASE("lexicographical comparison operators")
|
||||||
{
|
{
|
||||||
@@ -86,33 +87,23 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
|
|
||||||
SECTION("types")
|
SECTION("types")
|
||||||
{
|
{
|
||||||
std::vector<json::value_t> j_types =
|
std::vector<json::value_t> j_types = {
|
||||||
{
|
json::value_t::null, json::value_t::boolean, json::value_t::number_integer, json::value_t::number_unsigned, json::value_t::number_float,
|
||||||
json::value_t::null,
|
json::value_t::object, json::value_t::array, json::value_t::string, json::value_t::binary, json::value_t::discarded
|
||||||
json::value_t::boolean,
|
|
||||||
json::value_t::number_integer,
|
|
||||||
json::value_t::number_unsigned,
|
|
||||||
json::value_t::number_float,
|
|
||||||
json::value_t::object,
|
|
||||||
json::value_t::array,
|
|
||||||
json::value_t::string,
|
|
||||||
json::value_t::binary,
|
|
||||||
json::value_t::discarded
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::vector<bool>> expected_lt =
|
std::vector<std::vector<bool>> expected_lt = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9
|
//0 1 2 3 4 5 6 7 8 9
|
||||||
{f_, _t, _t, _t, _t, _t, _t, _t, _t, f_}, // 0
|
{ f_, _t, _t, _t, _t, _t, _t, _t, _t, f_ }, // 0
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, f_}, // 1
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, f_ }, // 1
|
||||||
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 2
|
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 2
|
||||||
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 3
|
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 3
|
||||||
{f_, f_, f_, f_, f_, _t, _t, _t, _t, f_}, // 4
|
{ f_, f_, f_, f_, f_, _t, _t, _t, _t, f_ }, // 4
|
||||||
{f_, f_, f_, f_, f_, f_, _t, _t, _t, f_}, // 5
|
{ f_, f_, f_, f_, f_, f_, _t, _t, _t, f_ }, // 5
|
||||||
{f_, f_, f_, f_, f_, f_, f_, _t, _t, f_}, // 6
|
{ f_, f_, f_, f_, f_, f_, f_, _t, _t, f_ }, // 6
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, f_}, // 7
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, f_ }, // 7
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
|
||||||
};
|
};
|
||||||
|
|
||||||
SECTION("comparison: less")
|
SECTION("comparison: less")
|
||||||
@@ -140,19 +131,18 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
||||||
SECTION("comparison: 3-way")
|
SECTION("comparison: 3-way")
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::partial_ordering>> expected =
|
std::vector<std::vector<std::partial_ordering>> expected = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9
|
//0 1 2 3 4 5 6 7 8 9
|
||||||
{eq, lt, lt, lt, lt, lt, lt, lt, lt, un}, // 0
|
{ eq, lt, lt, lt, lt, lt, lt, lt, lt, un }, // 0
|
||||||
{gt, eq, lt, lt, lt, lt, lt, lt, lt, un}, // 1
|
{ gt, eq, lt, lt, lt, lt, lt, lt, lt, un }, // 1
|
||||||
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 2
|
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 2
|
||||||
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 3
|
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 3
|
||||||
{gt, gt, eq, eq, eq, lt, lt, lt, lt, un}, // 4
|
{ gt, gt, eq, eq, eq, lt, lt, lt, lt, un }, // 4
|
||||||
{gt, gt, gt, gt, gt, eq, lt, lt, lt, un}, // 5
|
{ gt, gt, gt, gt, gt, eq, lt, lt, lt, un }, // 5
|
||||||
{gt, gt, gt, gt, gt, gt, eq, lt, lt, un}, // 6
|
{ gt, gt, gt, gt, gt, gt, eq, lt, lt, un }, // 6
|
||||||
{gt, gt, gt, gt, gt, gt, gt, eq, lt, un}, // 7
|
{ gt, gt, gt, gt, gt, gt, gt, eq, lt, un }, // 7
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, eq, un}, // 8
|
{ gt, gt, gt, gt, gt, gt, gt, gt, eq, un }, // 8
|
||||||
{un, un, un, un, un, un, un, un, un, un}, // 9
|
{ un, un, un, un, un, un, un, un, un, un }, // 9
|
||||||
};
|
};
|
||||||
|
|
||||||
// check expected partial_ordering against expected boolean
|
// check expected partial_ordering against expected boolean
|
||||||
@@ -177,7 +167,7 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
{
|
{
|
||||||
CAPTURE(i)
|
CAPTURE(i)
|
||||||
CAPTURE(j)
|
CAPTURE(j)
|
||||||
CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
|
CHECK((j_types[i] <=> j_types[j]) == expected[i][j]); // *NOPAD*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -186,102 +176,109 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
|
|
||||||
SECTION("values")
|
SECTION("values")
|
||||||
{
|
{
|
||||||
json j_values =
|
json j_values = {
|
||||||
{
|
nullptr,
|
||||||
nullptr, nullptr, // 0 1
|
nullptr, // 0 1
|
||||||
-17, 42, // 2 3
|
-17,
|
||||||
8u, 13u, // 4 5
|
42, // 2 3
|
||||||
3.14159, 23.42, // 6 7
|
8u,
|
||||||
nan, nan, // 8 9
|
13u, // 4 5
|
||||||
"foo", "bar", // 10 11
|
3.14159,
|
||||||
true, false, // 12 13
|
23.42, // 6 7
|
||||||
{1, 2, 3}, {"one", "two", "three"}, // 14 15
|
nan,
|
||||||
{{"first", 1}, {"second", 2}}, {{"a", "A"}, {"b", {"B"}}}, // 16 17
|
nan, // 8 9
|
||||||
json::binary({1, 2, 3}), json::binary({1, 2, 4}), // 18 19
|
"foo",
|
||||||
json(json::value_t::discarded), json(json::value_t::discarded) // 20 21
|
"bar", // 10 11
|
||||||
|
true,
|
||||||
|
false, // 12 13
|
||||||
|
{ 1, 2, 3 },
|
||||||
|
{ "one", "two", "three" }, // 14 15
|
||||||
|
{ { "first", 1 }, { "second", 2 } },
|
||||||
|
{ { "a", "A" }, { "b", { "B" } } }, // 16 17
|
||||||
|
json::binary({ 1, 2, 3 }),
|
||||||
|
json::binary({ 1, 2, 4 }), // 18 19
|
||||||
|
json(json::value_t::discarded),
|
||||||
|
json(json::value_t::discarded) // 20 21
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::vector<bool>> expected_eq =
|
std::vector<std::vector<bool>> expected_eq = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||||
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
|
{ _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 0
|
||||||
{_t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
|
{ _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 1
|
||||||
{f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
|
{ f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 2
|
||||||
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
|
{ f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 3
|
||||||
{f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
|
{ f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 4
|
||||||
{f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
|
{ f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 5
|
||||||
{f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
|
{ f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 6
|
||||||
{f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
|
{ f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 7
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 10
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 11
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 12
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, f_ }, // 13
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_}, // 14
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_ }, // 14
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_}, // 15
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_ }, // 15
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_}, // 16
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_ }, // 16
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_}, // 17
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_ }, // 17
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_}, // 18
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_ }, // 18
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 19
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_ }, // 19
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<std::vector<bool>> expected_lt =
|
std::vector<std::vector<bool>> expected_lt = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 0
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_ }, // 0
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_}, // 1
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_ }, // 1
|
||||||
{f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 2
|
{ f_, f_, f_, _t, _t, _t, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 2
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 3
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 3
|
||||||
{f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 4
|
{ f_, f_, f_, _t, f_, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 4
|
||||||
{f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 5
|
{ f_, f_, f_, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 5
|
||||||
{f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 6
|
{ f_, f_, f_, _t, _t, _t, f_, _t, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 6
|
||||||
{f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 7
|
{ f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 7
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 8
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 8
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 9
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 9
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 10
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 10
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 11
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 11
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 12
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 12
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_}, // 13
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, f_, _t, _t, _t, _t, _t, _t, f_, f_ }, // 13
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_}, // 14
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, _t, f_, f_, _t, _t, f_, f_ }, // 14
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_}, // 15
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_ }, // 15
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_}, // 16
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_, _t, _t, f_, f_ }, // 16
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_}, // 17
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, _t, _t, _t, f_, _t, _t, f_, f_ }, // 17
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_}, // 18
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, f_, f_ }, // 18
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 19
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
|
||||||
};
|
};
|
||||||
|
|
||||||
SECTION("compares unordered")
|
SECTION("compares unordered")
|
||||||
{
|
{
|
||||||
std::vector<std::vector<bool>> expected =
|
std::vector<std::vector<bool>> expected = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 0
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 0
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 1
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 1
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 2
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 2
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 3
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 3
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 4
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 4
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 5
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 5
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 6
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 6
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 7
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 7
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 8
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 8
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 9
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 9
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 10
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 10
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 11
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 11
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 12
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 12
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 13
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 13
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 14
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 14
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 15
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 15
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 16
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 16
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 17
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 17
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 18
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 18
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t}, // 19
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, _t, _t }, // 19
|
||||||
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 20
|
{ _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t }, // 20
|
||||||
{_t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t}, // 21
|
{ _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t, _t }, // 21
|
||||||
};
|
};
|
||||||
|
|
||||||
// check if two values compare unordered as expected
|
// check if two values compare unordered as expected
|
||||||
@@ -301,31 +298,30 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||||
SECTION("compares unordered (inverse)")
|
SECTION("compares unordered (inverse)")
|
||||||
{
|
{
|
||||||
std::vector<std::vector<bool>> expected =
|
std::vector<std::vector<bool>> expected = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 0
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 0
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 1
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 1
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 2
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 2
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 3
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 3
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 4
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 4
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 5
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 5
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 6
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 6
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 7
|
{ f_, f_, f_, f_, f_, f_, f_, f_, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 7
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 8
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 8
|
||||||
{f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 9
|
{ f_, f_, _t, _t, _t, _t, _t, _t, _t, _t, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 9
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 10
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 10
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 11
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 11
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 12
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 12
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 13
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 13
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 14
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 14
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 15
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 15
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 16
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 16
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 17
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 17
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 18
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 18
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 19
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 19
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 20
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 20
|
||||||
{f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_}, // 21
|
{ f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_, f_ }, // 21
|
||||||
};
|
};
|
||||||
|
|
||||||
// check that two values compare unordered as expected (with legacy-mode enabled)
|
// check that two values compare unordered as expected (with legacy-mode enabled)
|
||||||
@@ -496,31 +492,30 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
// JSON_HAS_CPP_20 (do not remove; see note at top of file)
|
||||||
SECTION("comparison: 3-way")
|
SECTION("comparison: 3-way")
|
||||||
{
|
{
|
||||||
std::vector<std::vector<std::partial_ordering>> expected =
|
std::vector<std::vector<std::partial_ordering>> expected = {
|
||||||
{
|
|
||||||
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
//0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
||||||
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 0
|
{ eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un }, // 0
|
||||||
{eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un}, // 1
|
{ eq, eq, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, un, un }, // 1
|
||||||
{gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 2
|
{ gt, gt, eq, lt, lt, lt, lt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 2
|
||||||
{gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 3
|
{ gt, gt, gt, eq, gt, gt, gt, gt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 3
|
||||||
{gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 4
|
{ gt, gt, gt, lt, eq, lt, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 4
|
||||||
{gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 5
|
{ gt, gt, gt, lt, gt, eq, gt, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 5
|
||||||
{gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 6
|
{ gt, gt, gt, lt, lt, lt, eq, lt, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 6
|
||||||
{gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 7
|
{ gt, gt, gt, lt, gt, gt, gt, eq, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 7
|
||||||
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 8
|
{ gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 8
|
||||||
{gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un}, // 9
|
{ gt, gt, un, un, un, un, un, un, un, un, lt, lt, gt, gt, lt, lt, lt, lt, lt, lt, un, un }, // 9
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 10
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, gt, gt, gt, gt, gt, gt, gt, lt, lt, un, un }, // 10
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un}, // 11
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, eq, gt, gt, gt, gt, gt, gt, lt, lt, un, un }, // 11
|
||||||
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un}, // 12
|
{ gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, gt, lt, lt, lt, lt, lt, lt, un, un }, // 12
|
||||||
{gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un}, // 13
|
{ gt, gt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, lt, eq, lt, lt, lt, lt, lt, lt, un, un }, // 13
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un}, // 14
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, eq, lt, gt, gt, lt, lt, un, un }, // 14
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un}, // 15
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, gt, eq, gt, gt, lt, lt, un, un }, // 15
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un}, // 16
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, eq, gt, lt, lt, un, un }, // 16
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un}, // 17
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, lt, lt, gt, gt, lt, lt, lt, eq, lt, lt, un, un }, // 17
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un}, // 18
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, lt, un, un }, // 18
|
||||||
{gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un}, // 19
|
{ gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, gt, eq, un, un }, // 19
|
||||||
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 20
|
{ un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un }, // 20
|
||||||
{un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un}, // 21
|
{ un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un, un }, // 21
|
||||||
};
|
};
|
||||||
|
|
||||||
// check expected partial_ordering against expected booleans
|
// check expected partial_ordering against expected booleans
|
||||||
@@ -552,7 +547,7 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
{
|
{
|
||||||
CAPTURE(i)
|
CAPTURE(i)
|
||||||
CAPTURE(j)
|
CAPTURE(j)
|
||||||
CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
|
CHECK((j_values[i] <=> j_values[j]) == expected[i][j]); // *NOPAD*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,20 +571,18 @@ TEST_CASE("lexicographical comparison operators")
|
|||||||
[1,2,[3,4,5],4,5]
|
[1,2,[3,4,5],4,5]
|
||||||
)";
|
)";
|
||||||
|
|
||||||
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
|
json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& j) noexcept {
|
||||||
{
|
|
||||||
// filter all number(2) elements
|
// filter all number(2) elements
|
||||||
return j != json(2);
|
return j != json(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
|
CHECK(j_object == json({ { "bar", { { "baz", 1 } } } }));
|
||||||
|
|
||||||
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json & j) noexcept
|
json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& j) noexcept {
|
||||||
{
|
|
||||||
return j != json(2);
|
return j != json(2);
|
||||||
});
|
});
|
||||||
|
|
||||||
CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
|
CHECK(j_array == json({ 1, { 3, 4, 5 }, 4, 5 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -52,8 +52,7 @@ TEST_CASE("concepts")
|
|||||||
// X::size_type must return an unsigned integer
|
// X::size_type must return an unsigned integer
|
||||||
CHECK((std::is_unsigned<json::size_type>::value));
|
CHECK((std::is_unsigned<json::size_type>::value));
|
||||||
// X::size_type can represent any non-negative value of X::difference_type
|
// X::size_type can represent any non-negative value of X::difference_type
|
||||||
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <=
|
CHECK(static_cast<json::size_type>((std::numeric_limits<json::difference_type>::max)()) <= (std::numeric_limits<json::size_type>::max)());
|
||||||
(std::numeric_limits<json::size_type>::max)());
|
|
||||||
|
|
||||||
// the expression "X u" has the post-condition "u.empty()"
|
// the expression "X u" has the post-condition "u.empty()"
|
||||||
{
|
{
|
||||||
@@ -130,7 +129,7 @@ TEST_CASE("concepts")
|
|||||||
SECTION("Swappable")
|
SECTION("Swappable")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j {1, 2, 3};
|
json j{ 1, 2, 3 };
|
||||||
json::iterator it1 = j.begin();
|
json::iterator it1 = j.begin();
|
||||||
json::iterator it2 = j.end();
|
json::iterator it2 = j.end();
|
||||||
swap(it1, it2);
|
swap(it1, it2);
|
||||||
@@ -138,7 +137,7 @@ TEST_CASE("concepts")
|
|||||||
CHECK(it2 == j.begin());
|
CHECK(it2 == j.begin());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j {1, 2, 3};
|
json j{ 1, 2, 3 };
|
||||||
json::const_iterator it1 = j.cbegin();
|
json::const_iterator it1 = j.cbegin();
|
||||||
json::const_iterator it2 = j.cend();
|
json::const_iterator it2 = j.cend();
|
||||||
swap(it1, it2);
|
swap(it1, it2);
|
||||||
|
|||||||
+186
-140
@@ -131,7 +131,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("filled object")
|
SECTION("filled object")
|
||||||
{
|
{
|
||||||
json::object_t const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
json::object_t const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) }, { "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
@@ -140,12 +140,14 @@ TEST_CASE("constructors")
|
|||||||
SECTION("create an object (implicit)")
|
SECTION("create an object (implicit)")
|
||||||
{
|
{
|
||||||
// reference object
|
// reference object
|
||||||
json::object_t const o_reference {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
json::object_t const o_reference{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j_reference(o_reference);
|
json const j_reference(o_reference);
|
||||||
|
|
||||||
SECTION("std::map<json::string_t, json>")
|
SECTION("std::map<json::string_t, json>")
|
||||||
{
|
{
|
||||||
std::map<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
std::map<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -153,11 +155,10 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::map<std::string, std::string> #600")
|
SECTION("std::map<std::string, std::string> #600")
|
||||||
{
|
{
|
||||||
const std::map<std::string, std::string> m
|
const std::map<std::string, std::string> m{
|
||||||
{
|
{ "a", "b" },
|
||||||
{"a", "b"},
|
{ "c", "d" },
|
||||||
{"c", "d"},
|
{ "e", "f" },
|
||||||
{"e", "f"},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
json const j(m);
|
json const j(m);
|
||||||
@@ -166,7 +167,8 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::map<const char*, json>")
|
SECTION("std::map<const char*, json>")
|
||||||
{
|
{
|
||||||
std::map<const char*, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
std::map<const char*, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -174,7 +176,8 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::multimap<json::string_t, json>")
|
SECTION("std::multimap<json::string_t, json>")
|
||||||
{
|
{
|
||||||
std::multimap<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
std::multimap<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -182,7 +185,8 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::unordered_map<json::string_t, json>")
|
SECTION("std::unordered_map<json::string_t, json>")
|
||||||
{
|
{
|
||||||
std::unordered_map<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
std::unordered_map<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -190,7 +194,8 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::unordered_multimap<json::string_t, json>")
|
SECTION("std::unordered_multimap<json::string_t, json>")
|
||||||
{
|
{
|
||||||
std::unordered_multimap<json::string_t, json> const o {{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}};
|
std::unordered_multimap<json::string_t, json> const o{ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) },
|
||||||
|
{ "d", json(false) }, { "e", json("string") }, { "f", json() } };
|
||||||
json const j(o);
|
json const j(o);
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -198,7 +203,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("associative container literal")
|
SECTION("associative container literal")
|
||||||
{
|
{
|
||||||
json const j({{"a", json(1)}, {"b", json(1u)}, {"c", json(2.2)}, {"d", json(false)}, {"e", json("string")}, {"f", json()}});
|
json const j({ { "a", json(1) }, { "b", json(1u) }, { "c", json(2.2) }, { "d", json(false) }, { "e", json("string") }, { "f", json() } });
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
}
|
}
|
||||||
@@ -215,7 +220,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("filled array")
|
SECTION("filled array")
|
||||||
{
|
{
|
||||||
json::array_t const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
json::array_t const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
@@ -224,12 +229,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("create an array (implicit)")
|
SECTION("create an array (implicit)")
|
||||||
{
|
{
|
||||||
// reference array
|
// reference array
|
||||||
json::array_t const a_reference {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
json::array_t const a_reference{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j_reference(a_reference);
|
json const j_reference(a_reference);
|
||||||
|
|
||||||
SECTION("std::list<json>")
|
SECTION("std::list<json>")
|
||||||
{
|
{
|
||||||
std::list<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::list<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -237,7 +242,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::pair")
|
SECTION("std::pair")
|
||||||
{
|
{
|
||||||
std::pair<float, std::string> const p{1.0f, "string"};
|
std::pair<float, std::string> const p{ 1.0f, "string" };
|
||||||
json const j(p);
|
json const j(p);
|
||||||
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
@@ -249,7 +254,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::pair with discarded values")
|
SECTION("std::pair with discarded values")
|
||||||
{
|
{
|
||||||
json const j{1, 2.0, "string"};
|
json const j{ 1, 2.0, "string" };
|
||||||
|
|
||||||
const auto p = j.get<std::pair<int, float>>();
|
const auto p = j.get<std::pair<int, float>>();
|
||||||
CHECK(p.first == j[0]);
|
CHECK(p.first == j[0]);
|
||||||
@@ -258,7 +263,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::tuple")
|
SECTION("std::tuple")
|
||||||
{
|
{
|
||||||
const auto t = std::make_tuple(1.0, std::string{"string"}, 42, std::vector<int> {0, 1});
|
const auto t = std::make_tuple(1.0, std::string{ "string" }, 42, std::vector<int>{ 0, 1 });
|
||||||
json const j(t);
|
json const j(t);
|
||||||
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
@@ -273,7 +278,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::tuple with discarded values")
|
SECTION("std::tuple with discarded values")
|
||||||
{
|
{
|
||||||
json const j{1, 2.0, "string", 42};
|
json const j{ 1, 2.0, "string", 42 };
|
||||||
|
|
||||||
const auto t = j.get<std::tuple<int, float, std::string>>();
|
const auto t = j.get<std::tuple<int, float, std::string>>();
|
||||||
CHECK(std::get<0>(t) == j[0]);
|
CHECK(std::get<0>(t) == j[0]);
|
||||||
@@ -283,7 +288,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::pair/tuple/array failures")
|
SECTION("std::pair/tuple/array failures")
|
||||||
{
|
{
|
||||||
json const j{1};
|
json const j{ 1 };
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS((j.get<std::pair<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS((j.get<std::pair<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS((j.get<std::tuple<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS((j.get<std::tuple<int, int>>()), "[json.exception.out_of_range.401] array index 1 is out of range", json::out_of_range&);
|
||||||
@@ -292,7 +297,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::forward_list<json>")
|
SECTION("std::forward_list<json>")
|
||||||
{
|
{
|
||||||
std::forward_list<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::forward_list<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -300,7 +305,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::array<json, 6>")
|
SECTION("std::array<json, 6>")
|
||||||
{
|
{
|
||||||
std::array<json, 6> const a {{json(1), json(1u), json(2.2), json(false), json("string"), json()}};
|
std::array<json, 6> const a{ { json(1), json(1u), json(2.2), json(false), json("string"), json() } };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -311,10 +316,10 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::valarray<int>")
|
SECTION("std::valarray<int>")
|
||||||
{
|
{
|
||||||
std::valarray<int> const va = {1, 2, 3, 4, 5};
|
std::valarray<int> const va = { 1, 2, 3, 4, 5 };
|
||||||
json const j(va);
|
json const j(va);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == json({1, 2, 3, 4, 5}));
|
CHECK(j == json({ 1, 2, 3, 4, 5 }));
|
||||||
|
|
||||||
auto jva = j.get<std::valarray<int>>();
|
auto jva = j.get<std::valarray<int>>();
|
||||||
CHECK(jva.size() == va.size());
|
CHECK(jva.size() == va.size());
|
||||||
@@ -326,10 +331,10 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::valarray<double>")
|
SECTION("std::valarray<double>")
|
||||||
{
|
{
|
||||||
std::valarray<double> const va = {1.2, 2.3, 3.4, 4.5, 5.6};
|
std::valarray<double> const va = { 1.2, 2.3, 3.4, 4.5, 5.6 };
|
||||||
json const j(va);
|
json const j(va);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == json({1.2, 2.3, 3.4, 4.5, 5.6}));
|
CHECK(j == json({ 1.2, 2.3, 3.4, 4.5, 5.6 }));
|
||||||
|
|
||||||
auto jva = j.get<std::valarray<double>>();
|
auto jva = j.get<std::valarray<double>>();
|
||||||
CHECK(jva.size() == va.size());
|
CHECK(jva.size() == va.size());
|
||||||
@@ -341,7 +346,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::vector<json>")
|
SECTION("std::vector<json>")
|
||||||
{
|
{
|
||||||
std::vector<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::vector<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -349,7 +354,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::deque<json>")
|
SECTION("std::deque<json>")
|
||||||
{
|
{
|
||||||
std::deque<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::deque<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -357,7 +362,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::set<json>")
|
SECTION("std::set<json>")
|
||||||
{
|
{
|
||||||
std::set<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::set<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
// we cannot really check for equality here
|
// we cannot really check for equality here
|
||||||
@@ -365,7 +370,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("std::unordered_set<json>")
|
SECTION("std::unordered_set<json>")
|
||||||
{
|
{
|
||||||
std::unordered_set<json> const a {json(1), json(1u), json(2.2), json(false), json("string"), json()};
|
std::unordered_set<json> const a{ json(1), json(1u), json(2.2), json(false), json("string"), json() };
|
||||||
json const j(a);
|
json const j(a);
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
// we cannot really check for equality here
|
// we cannot really check for equality here
|
||||||
@@ -373,7 +378,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("sequence container literal")
|
SECTION("sequence container literal")
|
||||||
{
|
{
|
||||||
json const j({json(1), json(1u), json(2.2), json(false), json("string"), json()});
|
json const j({ json(1), json(1u), json(2.2), json(false), json("string"), json() });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
}
|
}
|
||||||
@@ -390,7 +395,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("filled string")
|
SECTION("filled string")
|
||||||
{
|
{
|
||||||
json::string_t const s {"Hello world"};
|
json::string_t const s{ "Hello world" };
|
||||||
json const j(s);
|
json const j(s);
|
||||||
CHECK(j.type() == json::value_t::string);
|
CHECK(j.type() == json::value_t::string);
|
||||||
}
|
}
|
||||||
@@ -399,12 +404,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("create a string (implicit)")
|
SECTION("create a string (implicit)")
|
||||||
{
|
{
|
||||||
// reference string
|
// reference string
|
||||||
json::string_t const s_reference {"Hello world"};
|
json::string_t const s_reference{ "Hello world" };
|
||||||
json const j_reference(s_reference);
|
json const j_reference(s_reference);
|
||||||
|
|
||||||
SECTION("std::string")
|
SECTION("std::string")
|
||||||
{
|
{
|
||||||
std::string const s {"Hello world"};
|
std::string const s{ "Hello world" };
|
||||||
json const j(s);
|
json const j(s);
|
||||||
CHECK(j.type() == json::value_t::string);
|
CHECK(j.type() == json::value_t::string);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -412,7 +417,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("char[]")
|
SECTION("char[]")
|
||||||
{
|
{
|
||||||
char const s[] {"Hello world"}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
char const s[]{ "Hello world" }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
json const j(s);
|
json const j(s);
|
||||||
CHECK(j.type() == json::value_t::string);
|
CHECK(j.type() == json::value_t::string);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -420,7 +425,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("const char*")
|
SECTION("const char*")
|
||||||
{
|
{
|
||||||
const char* s {"Hello world"};
|
const char* s{ "Hello world" };
|
||||||
json const j(s);
|
json const j(s);
|
||||||
CHECK(j.type() == json::value_t::string);
|
CHECK(j.type() == json::value_t::string);
|
||||||
CHECK(j == j_reference);
|
CHECK(j == j_reference);
|
||||||
@@ -457,7 +462,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("from std::vector<bool>::reference")
|
SECTION("from std::vector<bool>::reference")
|
||||||
{
|
{
|
||||||
std::vector<bool> v{true};
|
std::vector<bool> v{ true };
|
||||||
json const j(v[0]);
|
json const j(v[0]);
|
||||||
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::reference>::value);
|
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::reference>::value);
|
||||||
CHECK(j.type() == json::value_t::boolean);
|
CHECK(j.type() == json::value_t::boolean);
|
||||||
@@ -465,7 +470,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("from std::vector<bool>::const_reference")
|
SECTION("from std::vector<bool>::const_reference")
|
||||||
{
|
{
|
||||||
const std::vector<bool> v{true};
|
const std::vector<bool> v{ true };
|
||||||
json const j(v[0]);
|
json const j(v[0]);
|
||||||
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::const_reference>::value);
|
CHECK(std::is_same<decltype(v[0]), std::vector<bool>::const_reference>::value);
|
||||||
CHECK(j.type() == json::value_t::boolean);
|
CHECK(j.type() == json::value_t::boolean);
|
||||||
@@ -483,7 +488,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("filled binary")
|
SECTION("filled binary")
|
||||||
{
|
{
|
||||||
json::binary_t const b({1, 2, 3});
|
json::binary_t const b({ 1, 2, 3 });
|
||||||
json const j(b);
|
json const j(b);
|
||||||
CHECK(j.type() == json::value_t::binary);
|
CHECK(j.type() == json::value_t::binary);
|
||||||
}
|
}
|
||||||
@@ -837,7 +842,7 @@ TEST_CASE("constructors")
|
|||||||
CHECK(j.type() == json::value_t::number_float);
|
CHECK(j.type() == json::value_t::number_float);
|
||||||
|
|
||||||
// check round trip of NaN
|
// check round trip of NaN
|
||||||
json::number_float_t const d{j};
|
json::number_float_t const d{ j };
|
||||||
CHECK((std::isnan(d) && std::isnan(n)) == true);
|
CHECK((std::isnan(d) && std::isnan(n)) == true);
|
||||||
|
|
||||||
// check that NaN is serialized to null
|
// check that NaN is serialized to null
|
||||||
@@ -852,7 +857,7 @@ TEST_CASE("constructors")
|
|||||||
CHECK(j.type() == json::value_t::number_float);
|
CHECK(j.type() == json::value_t::number_float);
|
||||||
|
|
||||||
// check round trip of infinity
|
// check round trip of infinity
|
||||||
json::number_float_t const d{j};
|
json::number_float_t const d{ j };
|
||||||
CHECK(d == n);
|
CHECK(d == n);
|
||||||
|
|
||||||
// check that inf is serialized to null
|
// check that inf is serialized to null
|
||||||
@@ -918,13 +923,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {});
|
json const j(json::initializer_list_t{});
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {};
|
json const j{};
|
||||||
CHECK(j.type() == json::value_t::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -935,13 +940,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(json::array_t())});
|
json const j(json::initializer_list_t{ json(json::array_t()) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {json::array_t()};
|
json const j{ json::array_t() };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -950,13 +955,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(json::object_t())});
|
json const j(json::initializer_list_t{ json(json::object_t()) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {json::object_t()};
|
json const j{ json::object_t() };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -965,13 +970,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json("Hello world")});
|
json const j(json::initializer_list_t{ json("Hello world") });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {"Hello world"};
|
json const j{ "Hello world" };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -980,13 +985,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(true)});
|
json const j(json::initializer_list_t{ json(true) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {true};
|
json const j{ true };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -995,13 +1000,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(1)});
|
json const j(json::initializer_list_t{ json(1) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {1};
|
json const j{ 1 };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1010,13 +1015,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(1u)});
|
json const j(json::initializer_list_t{ json(1u) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {1u};
|
json const j{ 1u };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1025,13 +1030,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {json(42.23)});
|
json const j(json::initializer_list_t{ json(42.23) });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {42.23};
|
json const j{ 42.23 };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1041,13 +1046,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
json const j(json::initializer_list_t {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()});
|
json const j(json::initializer_list_t{ 1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t() });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit")
|
SECTION("implicit")
|
||||||
{
|
{
|
||||||
json const j {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
|
json const j{ 1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t() };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1056,13 +1061,13 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} };
|
json const j{ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } };
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j { {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 };
|
json const j{ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false }, 13 };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1077,14 +1082,16 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
|
json const j = json::object({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } });
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("object with error")
|
SECTION("object with error")
|
||||||
{
|
{
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::object({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false}, 13 }), "[json.exception.type_error.301] cannot create object from initializer list", json::type_error&);
|
CHECK_THROWS_WITH_AS(_ = json::object({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false }, 13 }),
|
||||||
|
"[json.exception.type_error.301] cannot create object from initializer list",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("empty array")
|
SECTION("empty array")
|
||||||
@@ -1095,7 +1102,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j = json::array({ {"one", 1}, {"two", 1u}, {"three", 2.2}, {"four", false} });
|
json const j = json::array({ { "one", 1 }, { "two", 1u }, { "three", 2.2 }, { "four", false } });
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1109,7 +1116,7 @@ TEST_CASE("constructors")
|
|||||||
// This should break through any short string optimization in std::string
|
// This should break through any short string optimization in std::string
|
||||||
std::string source(1024, '!');
|
std::string source(1024, '!');
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j = {std::move(source)};
|
json j = { std::move(source) };
|
||||||
const auto* target_addr = j[0].get_ref<std::string const&>().data();
|
const auto* target_addr = j[0].get_ref<std::string const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1120,7 +1127,7 @@ TEST_CASE("constructors")
|
|||||||
// This should break through any short string optimization in std::string
|
// This should break through any short string optimization in std::string
|
||||||
std::string source(1024, '!');
|
std::string source(1024, '!');
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j = {{"key", std::move(source)}};
|
json j = { { "key", std::move(source) } };
|
||||||
const auto* target_addr = j["key"].get_ref<std::string const&>().data();
|
const auto* target_addr = j["key"].get_ref<std::string const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1131,7 +1138,7 @@ TEST_CASE("constructors")
|
|||||||
// This should break through any short string optimization in std::string
|
// This should break through any short string optimization in std::string
|
||||||
std::string source(1024, '!');
|
std::string source(1024, '!');
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j = {{std::move(source), 42}};
|
json j = { { std::move(source), 42 } };
|
||||||
const auto* target_addr = j.get_ref<json::object_t&>().begin()->first.data();
|
const auto* target_addr = j.get_ref<json::object_t&>().begin()->first.data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1142,9 +1149,9 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("constructor with implicit types (array)")
|
SECTION("constructor with implicit types (array)")
|
||||||
{
|
{
|
||||||
json::array_t source = {1, 2, 3};
|
json::array_t source = { 1, 2, 3 };
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j {std::move(source)};
|
json j{ std::move(source) };
|
||||||
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
|
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1152,9 +1159,9 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("constructor with implicit types (object)")
|
SECTION("constructor with implicit types (object)")
|
||||||
{
|
{
|
||||||
json::array_t source = {1, 2, 3};
|
json::array_t source = { 1, 2, 3 };
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json const j {{"key", std::move(source)}};
|
json const j{ { "key", std::move(source) } };
|
||||||
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
|
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1162,9 +1169,9 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("assignment with implicit types (array)")
|
SECTION("assignment with implicit types (array)")
|
||||||
{
|
{
|
||||||
json::array_t source = {1, 2, 3};
|
json::array_t source = { 1, 2, 3 };
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j = {std::move(source)};
|
json j = { std::move(source) };
|
||||||
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
|
const auto* target_addr = j[0].get_ref<json::array_t const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1172,9 +1179,9 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("assignment with implicit types (object)")
|
SECTION("assignment with implicit types (object)")
|
||||||
{
|
{
|
||||||
json::array_t source = {1, 2, 3};
|
json::array_t source = { 1, 2, 3 };
|
||||||
const auto* source_addr = source.data();
|
const auto* source_addr = source.data();
|
||||||
json j = {{"key", std::move(source)}};
|
json j = { { "key", std::move(source) } };
|
||||||
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
|
const auto* target_addr = j["key"].get_ref<json::array_t const&>().data();
|
||||||
const bool success = (target_addr == source_addr);
|
const bool success = (target_addr == source_addr);
|
||||||
CHECK(success);
|
CHECK(success);
|
||||||
@@ -1185,33 +1192,33 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("constructor with implicit types (array)")
|
SECTION("constructor with implicit types (array)")
|
||||||
{
|
{
|
||||||
json::object_t source = {{"hello", "world"}};
|
json::object_t source = { { "hello", "world" } };
|
||||||
const json* source_addr = &source.at("hello");
|
const json* source_addr = &source.at("hello");
|
||||||
json j {std::move(source)};
|
json j{ std::move(source) };
|
||||||
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("constructor with implicit types (object)")
|
SECTION("constructor with implicit types (object)")
|
||||||
{
|
{
|
||||||
json::object_t source = {{"hello", "world"}};
|
json::object_t source = { { "hello", "world" } };
|
||||||
const json* source_addr = &source.at("hello");
|
const json* source_addr = &source.at("hello");
|
||||||
json j {{"key", std::move(source)}};
|
json j{ { "key", std::move(source) } };
|
||||||
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("assignment with implicit types (array)")
|
SECTION("assignment with implicit types (array)")
|
||||||
{
|
{
|
||||||
json::object_t source = {{"hello", "world"}};
|
json::object_t source = { { "hello", "world" } };
|
||||||
const json* source_addr = &source.at("hello");
|
const json* source_addr = &source.at("hello");
|
||||||
json j = {std::move(source)};
|
json j = { std::move(source) };
|
||||||
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("assignment with implicit types (object)")
|
SECTION("assignment with implicit types (object)")
|
||||||
{
|
{
|
||||||
json::object_t source = {{"hello", "world"}};
|
json::object_t source = { { "hello", "world" } };
|
||||||
const json* source_addr = &source.at("hello");
|
const json* source_addr = &source.at("hello");
|
||||||
json j = {{"key", std::move(source)}};
|
json j = { { "key", std::move(source) } };
|
||||||
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1220,37 +1227,36 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("constructor with implicit types (array)")
|
SECTION("constructor with implicit types (array)")
|
||||||
{
|
{
|
||||||
json source {1, 2, 3};
|
json source{ 1, 2, 3 };
|
||||||
const json* source_addr = &source[0];
|
const json* source_addr = &source[0];
|
||||||
json j {std::move(source), {}};
|
json j{ std::move(source), {} };
|
||||||
CHECK(&j[0][0] == source_addr);
|
CHECK(&j[0][0] == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("constructor with implicit types (object)")
|
SECTION("constructor with implicit types (object)")
|
||||||
{
|
{
|
||||||
json source {1, 2, 3};
|
json source{ 1, 2, 3 };
|
||||||
const json* source_addr = &source[0];
|
const json* source_addr = &source[0];
|
||||||
json j {{"key", std::move(source)}};
|
json j{ { "key", std::move(source) } };
|
||||||
CHECK(&j["key"][0] == source_addr);
|
CHECK(&j["key"][0] == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("assignment with implicit types (array)")
|
SECTION("assignment with implicit types (array)")
|
||||||
{
|
{
|
||||||
json source {1, 2, 3};
|
json source{ 1, 2, 3 };
|
||||||
const json* source_addr = &source[0];
|
const json* source_addr = &source[0];
|
||||||
json j = {std::move(source), {}};
|
json j = { std::move(source), {} };
|
||||||
CHECK(&j[0][0] == source_addr);
|
CHECK(&j[0][0] == source_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("assignment with implicit types (object)")
|
SECTION("assignment with implicit types (object)")
|
||||||
{
|
{
|
||||||
json source {1, 2, 3};
|
json source{ 1, 2, 3 };
|
||||||
const json* source_addr = &source[0];
|
const json* source_addr = &source[0];
|
||||||
json j = {{"key", std::move(source)}};
|
json j = { { "key", std::move(source) } };
|
||||||
CHECK(&j["key"][0] == source_addr);
|
CHECK(&j["key"][0] == source_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1258,14 +1264,14 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
SECTION("cnt = 0")
|
SECTION("cnt = 0")
|
||||||
{
|
{
|
||||||
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
|
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
|
||||||
json const arr(0, v);
|
json const arr(0, v);
|
||||||
CHECK(arr.size() == 0);
|
CHECK(arr.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("cnt = 1")
|
SECTION("cnt = 1")
|
||||||
{
|
{
|
||||||
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
|
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
|
||||||
json const arr(1, v);
|
json const arr(1, v);
|
||||||
CHECK(arr.size() == 1);
|
CHECK(arr.size() == 1);
|
||||||
for (const auto& x : arr)
|
for (const auto& x : arr)
|
||||||
@@ -1276,7 +1282,7 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("cnt = 3")
|
SECTION("cnt = 3")
|
||||||
{
|
{
|
||||||
json const v = {1, "foo", 34.23, {1, 2, 3}, {{"A", 1}, {"B", 2u}}};
|
json const v = { 1, "foo", 34.23, { 1, 2, 3 }, { { "A", 1 }, { "B", 2u } } };
|
||||||
json const arr(3, v);
|
json const arr(3, v);
|
||||||
CHECK(arr.size() == 3);
|
CHECK(arr.size() == 3);
|
||||||
for (const auto& x : arr)
|
for (const auto& x : arr)
|
||||||
@@ -1293,12 +1299,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("json(begin(), end())")
|
SECTION("json(begin(), end())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
json const j_new(jobject.begin(), jobject.end());
|
json const j_new(jobject.begin(), jobject.end());
|
||||||
CHECK(j_new == jobject);
|
CHECK(j_new == jobject);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
json const j_new(jobject.cbegin(), jobject.cend());
|
json const j_new(jobject.cbegin(), jobject.cend());
|
||||||
CHECK(j_new == jobject);
|
CHECK(j_new == jobject);
|
||||||
}
|
}
|
||||||
@@ -1307,12 +1313,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("json(begin(), begin())")
|
SECTION("json(begin(), begin())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
json const j_new(jobject.begin(), jobject.begin());
|
json const j_new(jobject.begin(), jobject.begin());
|
||||||
CHECK(j_new == json::object());
|
CHECK(j_new == json::object());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
json const j_new(jobject.cbegin(), jobject.cbegin());
|
json const j_new(jobject.cbegin(), jobject.cbegin());
|
||||||
CHECK(j_new == json::object());
|
CHECK(j_new == json::object());
|
||||||
}
|
}
|
||||||
@@ -1320,24 +1326,32 @@ TEST_CASE("constructors")
|
|||||||
|
|
||||||
SECTION("construct from subrange")
|
SECTION("construct from subrange")
|
||||||
{
|
{
|
||||||
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
|
||||||
json const j_new(jobject.find("b"), jobject.find("e"));
|
json const j_new(jobject.find("b"), jobject.find("e"));
|
||||||
CHECK(j_new == json({{"b", 1}, {"c", 17u}, {"d", false}}));
|
CHECK(j_new == json({ { "b", 1 }, { "c", 17u }, { "d", false } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("incompatible iterators")
|
SECTION("incompatible iterators")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
json jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
|
||||||
json jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json jobject2 = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
CHECK_THROWS_WITH_AS(json(jobject.begin(), jobject2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(jobject.begin(), jobject2.end()),
|
||||||
CHECK_THROWS_WITH_AS(json(jobject2.begin(), jobject.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(json(jobject2.begin(), jobject.end()),
|
||||||
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jobject = {{"a", "a"}, {"b", 1}, {"c", 17u}, {"d", false}, {"e", true}};
|
json const jobject = { { "a", "a" }, { "b", 1 }, { "c", 17u }, { "d", false }, { "e", true } };
|
||||||
json const jobject2 = {{"a", "a"}, {"b", 1}, {"c", 17u}};
|
json const jobject2 = { { "a", "a" }, { "b", 1 }, { "c", 17u } };
|
||||||
CHECK_THROWS_WITH_AS(json(jobject.cbegin(), jobject2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(jobject.cbegin(), jobject2.cend()),
|
||||||
CHECK_THROWS_WITH_AS(json(jobject2.cbegin(), jobject.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(json(jobject2.cbegin(), jobject.cend()),
|
||||||
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1347,12 +1361,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("json(begin(), end())")
|
SECTION("json(begin(), end())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 2, 3, 4, 5};
|
json jarray = { 1, 2, 3, 4, 5 };
|
||||||
json const j_new(jarray.begin(), jarray.end());
|
json const j_new(jarray.begin(), jarray.end());
|
||||||
CHECK(j_new == jarray);
|
CHECK(j_new == jarray);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jarray = {1, 2, 3, 4, 5};
|
json const jarray = { 1, 2, 3, 4, 5 };
|
||||||
json const j_new(jarray.cbegin(), jarray.cend());
|
json const j_new(jarray.cbegin(), jarray.cend());
|
||||||
CHECK(j_new == jarray);
|
CHECK(j_new == jarray);
|
||||||
}
|
}
|
||||||
@@ -1361,12 +1375,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("json(begin(), begin())")
|
SECTION("json(begin(), begin())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 2, 3, 4, 5};
|
json jarray = { 1, 2, 3, 4, 5 };
|
||||||
json j_new(jarray.begin(), jarray.begin());
|
json j_new(jarray.begin(), jarray.begin());
|
||||||
CHECK(j_new == json::array());
|
CHECK(j_new == json::array());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jarray = {1, 2, 3, 4, 5};
|
json const jarray = { 1, 2, 3, 4, 5 };
|
||||||
json const j_new(jarray.cbegin(), jarray.cbegin());
|
json const j_new(jarray.cbegin(), jarray.cbegin());
|
||||||
CHECK(j_new == json::array());
|
CHECK(j_new == json::array());
|
||||||
}
|
}
|
||||||
@@ -1375,30 +1389,38 @@ TEST_CASE("constructors")
|
|||||||
SECTION("construct from subrange")
|
SECTION("construct from subrange")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 2, 3, 4, 5};
|
json jarray = { 1, 2, 3, 4, 5 };
|
||||||
json const j_new(jarray.begin() + 1, jarray.begin() + 3);
|
json const j_new(jarray.begin() + 1, jarray.begin() + 3);
|
||||||
CHECK(j_new == json({2, 3}));
|
CHECK(j_new == json({ 2, 3 }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jarray = {1, 2, 3, 4, 5};
|
json const jarray = { 1, 2, 3, 4, 5 };
|
||||||
json const j_new(jarray.cbegin() + 1, jarray.cbegin() + 3);
|
json const j_new(jarray.cbegin() + 1, jarray.cbegin() + 3);
|
||||||
CHECK(j_new == json({2, 3}));
|
CHECK(j_new == json({ 2, 3 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("incompatible iterators")
|
SECTION("incompatible iterators")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 2, 3, 4};
|
json jarray = { 1, 2, 3, 4 };
|
||||||
json jarray2 = {2, 3, 4, 5};
|
json jarray2 = { 2, 3, 4, 5 };
|
||||||
CHECK_THROWS_WITH_AS(json(jarray.begin(), jarray2.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(jarray.begin(), jarray2.end()),
|
||||||
CHECK_THROWS_WITH_AS(json(jarray2.begin(), jarray.end()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(json(jarray2.begin(), jarray.end()),
|
||||||
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const jarray = {1, 2, 3, 4};
|
json const jarray = { 1, 2, 3, 4 };
|
||||||
json const jarray2 = {2, 3, 4, 5};
|
json const jarray2 = { 2, 3, 4, 5 };
|
||||||
CHECK_THROWS_WITH_AS(json(jarray.cbegin(), jarray2.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(jarray.cbegin(), jarray2.cend()),
|
||||||
CHECK_THROWS_WITH_AS(json(jarray2.cbegin(), jarray.cend()), "[json.exception.invalid_iterator.201] iterators are not compatible", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(json(jarray2.cbegin(), jarray.cend()),
|
||||||
|
"[json.exception.invalid_iterator.201] iterators are not compatible",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1411,11 +1433,15 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.end()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.end()),
|
||||||
|
"[json.exception.invalid_iterator.206] cannot construct with iterators from null",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cend()), "[json.exception.invalid_iterator.206] cannot construct with iterators from null", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cend()),
|
||||||
|
"[json.exception.invalid_iterator.206] cannot construct with iterators from null",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1492,12 +1518,12 @@ TEST_CASE("constructors")
|
|||||||
SECTION("binary")
|
SECTION("binary")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json const j_new(j.begin(), j.end());
|
json const j_new(j.begin(), j.end());
|
||||||
CHECK((j == j_new));
|
CHECK((j == j_new));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = json::binary({1, 2, 3});
|
json const j = json::binary({ 1, 2, 3 });
|
||||||
json const j_new(j.cbegin(), j.cend());
|
json const j_new(j.cbegin(), j.cend());
|
||||||
CHECK((j == j_new));
|
CHECK((j == j_new));
|
||||||
}
|
}
|
||||||
@@ -1511,12 +1537,16 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
json j = "foo";
|
json j = "foo";
|
||||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = "bar";
|
json const j = "bar";
|
||||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1525,12 +1555,16 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
json j = false;
|
json j = false;
|
||||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = true;
|
json const j = true;
|
||||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1539,12 +1573,16 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
json j = 17;
|
json j = 17;
|
||||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = 17;
|
json const j = 17;
|
||||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1553,12 +1591,16 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
json j = 17u;
|
json j = 17u;
|
||||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = 17u;
|
json const j = 17u;
|
||||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1567,12 +1609,16 @@ TEST_CASE("constructors")
|
|||||||
{
|
{
|
||||||
json j = 23.42;
|
json j = 23.42;
|
||||||
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json const j = 23.42;
|
json const j = 23.42;
|
||||||
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(json(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,82 +17,82 @@ TEST_CASE("other constructors and destructor")
|
|||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j {{"foo", 1}, {"bar", false}};
|
json j{ { "foo", 1 }, { "bar", false } };
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j {"foo", 1, 42.23, false};
|
json j{ "foo", 1, 42.23, false };
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("null")
|
SECTION("null")
|
||||||
{
|
{
|
||||||
json j(nullptr);
|
json j(nullptr);
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("boolean")
|
SECTION("boolean")
|
||||||
{
|
{
|
||||||
json j(true);
|
json j(true);
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json j("Hello world");
|
json j("Hello world");
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
{
|
{
|
||||||
json j(42);
|
json j(42);
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (unsigned)")
|
SECTION("number (unsigned)")
|
||||||
{
|
{
|
||||||
json j(42u);
|
json j(42u);
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (floating-point)")
|
SECTION("number (floating-point)")
|
||||||
{
|
{
|
||||||
json j(42.23);
|
json j(42.23);
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("binary")
|
SECTION("binary")
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
json k(j); // NOLINT(performance-unnecessary-copy-initialization)
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("move constructor")
|
SECTION("move constructor")
|
||||||
{
|
{
|
||||||
json j {{"foo", "bar"}, {"baz", {1, 2, 3, 4}}, {"a", 42u}, {"b", 42.23}, {"c", nullptr}};
|
json j{ { "foo", "bar" }, { "baz", { 1, 2, 3, 4 } }, { "a", 42u }, { "b", 42.23 }, { "c", nullptr } };
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
const json k(std::move(j));
|
const json k(std::move(j));
|
||||||
CHECK(k.type() == json::value_t::object);
|
CHECK(k.type() == json::value_t::object);
|
||||||
CHECK(j.type() == json::value_t::null); // NOLINT: access after move is OK here
|
CHECK(j.type() == json::value_t::null); // NOLINT: access after move is OK here
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy assignment")
|
SECTION("copy assignment")
|
||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j {{"foo", 1}, {"bar", false}};
|
json j{ { "foo", 1 }, { "bar", false } };
|
||||||
json k;
|
json k;
|
||||||
k = j;
|
k = j;
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
@@ -100,7 +100,7 @@ TEST_CASE("other constructors and destructor")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j {"foo", 1, 42.23, false};
|
json j{ "foo", 1, 42.23, false };
|
||||||
json k;
|
json k;
|
||||||
k = j;
|
k = j;
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
@@ -156,7 +156,7 @@ TEST_CASE("other constructors and destructor")
|
|||||||
|
|
||||||
SECTION("binary")
|
SECTION("binary")
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json k;
|
json k;
|
||||||
k = j;
|
k = j;
|
||||||
CHECK(j == k);
|
CHECK(j == k);
|
||||||
@@ -167,20 +167,20 @@ TEST_CASE("other constructors and destructor")
|
|||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
auto* j = new json {{"foo", 1}, {"bar", false}}; // NOLINT(cppcoreguidelines-owning-memory)
|
auto* j = new json{ { "foo", 1 }, { "bar", false } }; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
auto* j = new json {"foo", 1, 1u, false, 23.42}; // NOLINT(cppcoreguidelines-owning-memory)
|
auto* j = new json{ "foo", 1, 1u, false, 23.42 }; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
auto* j = new json("Hello world"); // NOLINT(cppcoreguidelines-owning-memory)
|
auto* j = new json("Hello world"); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
delete j; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ struct alt_string_iter
|
|||||||
{
|
{
|
||||||
alt_string_iter() = default;
|
alt_string_iter() = default;
|
||||||
alt_string_iter(const char* cstr)
|
alt_string_iter(const char* cstr)
|
||||||
: impl(cstr)
|
: impl(cstr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void reserve(std::size_t s)
|
void reserve(std::size_t s)
|
||||||
@@ -62,7 +62,7 @@ struct alt_string_data
|
|||||||
{
|
{
|
||||||
alt_string_data() = default;
|
alt_string_data() = default;
|
||||||
alt_string_data(const char* cstr)
|
alt_string_data(const char* cstr)
|
||||||
: impl(cstr)
|
: impl(cstr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void reserve(std::size_t s)
|
void reserve(std::size_t s)
|
||||||
@@ -102,7 +102,7 @@ void check_escaped(const char* original, const char* escaped, const bool ensure_
|
|||||||
s.dump_escaped(original, ensure_ascii);
|
s.dump_escaped(original, ensure_ascii);
|
||||||
CHECK(ss.str() == escaped);
|
CHECK(ss.str() == escaped);
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("convenience functions")
|
TEST_CASE("convenience functions")
|
||||||
{
|
{
|
||||||
@@ -173,8 +173,8 @@ TEST_CASE("convenience functions")
|
|||||||
using nlohmann::detail::concat;
|
using nlohmann::detail::concat;
|
||||||
|
|
||||||
const char* expected = "Hello, world!";
|
const char* expected = "Hello, world!";
|
||||||
alt_string_iter const hello_iter{"Hello, "};
|
alt_string_iter const hello_iter{ "Hello, " };
|
||||||
alt_string_data const hello_data{"Hello, "};
|
alt_string_data const hello_data{ "Hello, " };
|
||||||
std::string const world = "world";
|
std::string const world = "world";
|
||||||
|
|
||||||
SECTION("std::string")
|
SECTION("std::string")
|
||||||
|
|||||||
+287
-328
File diff suppressed because it is too large
Load Diff
@@ -30,25 +30,23 @@ class json_metadata
|
|||||||
{
|
{
|
||||||
return m_metadata;
|
return m_metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
metadata_t m_metadata = {};
|
metadata_t m_metadata = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
using json_with_metadata =
|
using json_with_metadata = nlohmann::basic_json<std::map,
|
||||||
nlohmann::basic_json <
|
std::vector,
|
||||||
std::map,
|
std::string,
|
||||||
std::vector,
|
bool,
|
||||||
std::string,
|
std::int64_t,
|
||||||
bool,
|
std::uint64_t,
|
||||||
std::int64_t,
|
double,
|
||||||
std::uint64_t,
|
std::allocator,
|
||||||
double,
|
nlohmann::adl_serializer,
|
||||||
std::allocator,
|
std::vector<std::uint8_t>,
|
||||||
nlohmann::adl_serializer,
|
json_metadata<T>>;
|
||||||
std::vector<std::uint8_t>,
|
|
||||||
json_metadata<T>
|
|
||||||
>;
|
|
||||||
|
|
||||||
TEST_CASE("JSON Node Metadata")
|
TEST_CASE("JSON Node Metadata")
|
||||||
{
|
{
|
||||||
@@ -56,18 +54,18 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
{
|
{
|
||||||
using json = json_with_metadata<int>;
|
using json = json_with_metadata<int>;
|
||||||
json null;
|
json null;
|
||||||
auto obj = json::object();
|
auto obj = json::object();
|
||||||
auto array = json::array();
|
auto array = json::array();
|
||||||
|
|
||||||
null.metadata() = 1;
|
null.metadata() = 1;
|
||||||
obj.metadata() = 2;
|
obj.metadata() = 2;
|
||||||
array.metadata() = 3;
|
array.metadata() = 3;
|
||||||
auto copy = array;
|
auto copy = array;
|
||||||
|
|
||||||
CHECK(null.metadata() == 1);
|
CHECK(null.metadata() == 1);
|
||||||
CHECK(obj.metadata() == 2);
|
CHECK(obj.metadata() == 2);
|
||||||
CHECK(array.metadata() == 3);
|
CHECK(array.metadata() == 3);
|
||||||
CHECK(copy.metadata() == 3);
|
CHECK(copy.metadata() == 3);
|
||||||
}
|
}
|
||||||
SECTION("type vector<int>")
|
SECTION("type vector<int>")
|
||||||
{
|
{
|
||||||
@@ -77,11 +75,11 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
auto copy = value;
|
auto copy = value;
|
||||||
value.metadata().emplace_back(2);
|
value.metadata().emplace_back(2);
|
||||||
|
|
||||||
CHECK(copy.metadata().size() == 1);
|
CHECK(copy.metadata().size() == 1);
|
||||||
CHECK(copy.metadata().at(0) == 1);
|
CHECK(copy.metadata().at(0) == 1);
|
||||||
CHECK(value.metadata().size() == 2);
|
CHECK(value.metadata().size() == 2);
|
||||||
CHECK(value.metadata().at(0) == 1);
|
CHECK(value.metadata().at(0) == 1);
|
||||||
CHECK(value.metadata().at(1) == 2);
|
CHECK(value.metadata().at(1) == 2);
|
||||||
}
|
}
|
||||||
SECTION("copy ctor")
|
SECTION("copy ctor")
|
||||||
{
|
{
|
||||||
@@ -92,15 +90,15 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
|
|
||||||
json copy = value;
|
json copy = value;
|
||||||
|
|
||||||
CHECK(copy.metadata().size() == 2);
|
CHECK(copy.metadata().size() == 2);
|
||||||
CHECK(copy.metadata().at(0) == 1);
|
CHECK(copy.metadata().at(0) == 1);
|
||||||
CHECK(copy.metadata().at(1) == 2);
|
CHECK(copy.metadata().at(1) == 2);
|
||||||
CHECK(value.metadata().size() == 2);
|
CHECK(value.metadata().size() == 2);
|
||||||
CHECK(value.metadata().at(0) == 1);
|
CHECK(value.metadata().at(0) == 1);
|
||||||
CHECK(value.metadata().at(1) == 2);
|
CHECK(value.metadata().at(1) == 2);
|
||||||
|
|
||||||
value.metadata().clear();
|
value.metadata().clear();
|
||||||
CHECK(copy.metadata().size() == 2);
|
CHECK(copy.metadata().size() == 2);
|
||||||
CHECK(value.metadata().size() == 0);
|
CHECK(value.metadata().size() == 0);
|
||||||
}
|
}
|
||||||
SECTION("move ctor")
|
SECTION("move ctor")
|
||||||
@@ -112,9 +110,9 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
|
|
||||||
const json moved = std::move(value);
|
const json moved = std::move(value);
|
||||||
|
|
||||||
CHECK(moved.metadata().size() == 2);
|
CHECK(moved.metadata().size() == 2);
|
||||||
CHECK(moved.metadata().at(0) == 1);
|
CHECK(moved.metadata().at(0) == 1);
|
||||||
CHECK(moved.metadata().at(1) == 2);
|
CHECK(moved.metadata().at(1) == 2);
|
||||||
}
|
}
|
||||||
SECTION("move assign")
|
SECTION("move assign")
|
||||||
{
|
{
|
||||||
@@ -126,9 +124,9 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
json moved;
|
json moved;
|
||||||
moved = std::move(value);
|
moved = std::move(value);
|
||||||
|
|
||||||
CHECK(moved.metadata().size() == 2);
|
CHECK(moved.metadata().size() == 2);
|
||||||
CHECK(moved.metadata().at(0) == 1);
|
CHECK(moved.metadata().at(0) == 1);
|
||||||
CHECK(moved.metadata().at(1) == 2);
|
CHECK(moved.metadata().at(1) == 2);
|
||||||
}
|
}
|
||||||
SECTION("copy assign")
|
SECTION("copy assign")
|
||||||
{
|
{
|
||||||
@@ -140,22 +138,22 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
json copy;
|
json copy;
|
||||||
copy = value;
|
copy = value;
|
||||||
|
|
||||||
CHECK(copy.metadata().size() == 2);
|
CHECK(copy.metadata().size() == 2);
|
||||||
CHECK(copy.metadata().at(0) == 1);
|
CHECK(copy.metadata().at(0) == 1);
|
||||||
CHECK(copy.metadata().at(1) == 2);
|
CHECK(copy.metadata().at(1) == 2);
|
||||||
CHECK(value.metadata().size() == 2);
|
CHECK(value.metadata().size() == 2);
|
||||||
CHECK(value.metadata().at(0) == 1);
|
CHECK(value.metadata().at(0) == 1);
|
||||||
CHECK(value.metadata().at(1) == 2);
|
CHECK(value.metadata().at(1) == 2);
|
||||||
|
|
||||||
value.metadata().clear();
|
value.metadata().clear();
|
||||||
CHECK(copy.metadata().size() == 2);
|
CHECK(copy.metadata().size() == 2);
|
||||||
CHECK(value.metadata().size() == 0);
|
CHECK(value.metadata().size() == 0);
|
||||||
}
|
}
|
||||||
SECTION("type unique_ptr<int>")
|
SECTION("type unique_ptr<int>")
|
||||||
{
|
{
|
||||||
using json = json_with_metadata<std::unique_ptr<int>>;
|
using json = json_with_metadata<std::unique_ptr<int>>;
|
||||||
json value;
|
json value;
|
||||||
value.metadata().reset(new int(42)); // NOLINT(cppcoreguidelines-owning-memory)
|
value.metadata().reset(new int(42)); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
auto moved = std::move(value);
|
auto moved = std::move(value);
|
||||||
|
|
||||||
CHECK(moved.metadata() != nullptr);
|
CHECK(moved.metadata() != nullptr);
|
||||||
@@ -171,14 +169,14 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
json const array(10, value);
|
json const array(10, value);
|
||||||
|
|
||||||
CHECK(value.metadata().size() == 2);
|
CHECK(value.metadata().size() == 2);
|
||||||
CHECK(value.metadata().at(0) == 1);
|
CHECK(value.metadata().at(0) == 1);
|
||||||
CHECK(value.metadata().at(1) == 2);
|
CHECK(value.metadata().at(1) == 2);
|
||||||
|
|
||||||
for (const auto& val : array)
|
for (const auto& val : array)
|
||||||
{
|
{
|
||||||
CHECK(val.metadata().size() == 2);
|
CHECK(val.metadata().size() == 2);
|
||||||
CHECK(val.metadata().at(0) == 1);
|
CHECK(val.metadata().at(0) == 1);
|
||||||
CHECK(val.metadata().at(1) == 2);
|
CHECK(val.metadata().at(1) == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,38 +186,37 @@ TEST_CASE("JSON Node Metadata")
|
|||||||
class visitor_adaptor
|
class visitor_adaptor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template <class Fnc>
|
template<class Fnc>
|
||||||
void visit(const Fnc& fnc) const;
|
void visit(const Fnc& fnc) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
template <class Ptr, class Fnc>
|
template<class Ptr, class Fnc>
|
||||||
void do_visit(const Ptr& ptr, const Fnc& fnc) const;
|
void do_visit(const Ptr& ptr, const Fnc& fnc) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
using json_with_visitor_t = nlohmann::basic_json <
|
using json_with_visitor_t = nlohmann::basic_json<std::map,
|
||||||
std::map,
|
std::vector,
|
||||||
std::vector,
|
std::string,
|
||||||
std::string,
|
bool,
|
||||||
bool,
|
std::int64_t,
|
||||||
std::int64_t,
|
std::uint64_t,
|
||||||
std::uint64_t,
|
double,
|
||||||
double,
|
std::allocator,
|
||||||
std::allocator,
|
nlohmann::adl_serializer,
|
||||||
nlohmann::adl_serializer,
|
std::vector<std::uint8_t>,
|
||||||
std::vector<std::uint8_t>,
|
visitor_adaptor>;
|
||||||
visitor_adaptor
|
|
||||||
>;
|
|
||||||
|
|
||||||
template <class Fnc>
|
template<class Fnc>
|
||||||
void visitor_adaptor::visit(const Fnc& fnc) const
|
void visitor_adaptor::visit(const Fnc& fnc) const
|
||||||
{
|
{
|
||||||
do_visit(json_with_visitor_t::json_pointer{}, fnc);
|
do_visit(json_with_visitor_t::json_pointer{}, fnc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class Ptr, class Fnc>
|
template<class Ptr, class Fnc>
|
||||||
void visitor_adaptor::do_visit(const Ptr& ptr, const Fnc& fnc) const
|
void visitor_adaptor::do_visit(const Ptr& ptr, const Fnc& fnc) const
|
||||||
{
|
{
|
||||||
using value_t = nlohmann::detail::value_t;
|
using value_t = nlohmann::detail::value_t;
|
||||||
const json_with_visitor_t& json = *static_cast<const json_with_visitor_t*>(this); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
const json_with_visitor_t& json = *static_cast<const json_with_visitor_t*>(this); // NOLINT(cppcoreguidelines-pro-type-static-cast-downcast)
|
||||||
switch (json.type())
|
switch (json.type())
|
||||||
{
|
{
|
||||||
case value_t::object:
|
case value_t::object:
|
||||||
@@ -252,7 +249,7 @@ TEST_CASE("JSON Visit Node")
|
|||||||
{
|
{
|
||||||
json_with_visitor_t json;
|
json_with_visitor_t json;
|
||||||
json["null"];
|
json["null"];
|
||||||
json["int"] = -1;
|
json["int"] = -1;
|
||||||
json["uint"] = 1U;
|
json["uint"] = 1U;
|
||||||
json["float"] = 1.0;
|
json["float"] = 1.0;
|
||||||
json["boolean"] = true;
|
json["boolean"] = true;
|
||||||
@@ -261,33 +258,27 @@ TEST_CASE("JSON Visit Node")
|
|||||||
json["array"].push_back(1);
|
json["array"].push_back(1);
|
||||||
json["array"].push_back(json);
|
json["array"].push_back(json);
|
||||||
|
|
||||||
std::set<std::string> expected
|
std::set<std::string> expected{ "/null - null - null",
|
||||||
{
|
"/int - number_integer - -1",
|
||||||
"/null - null - null",
|
"/uint - number_unsigned - 1",
|
||||||
"/int - number_integer - -1",
|
"/float - number_float - 1.0",
|
||||||
"/uint - number_unsigned - 1",
|
"/boolean - boolean - true",
|
||||||
"/float - number_float - 1.0",
|
"/string - string - \"string\"",
|
||||||
"/boolean - boolean - true",
|
"/array/0 - number_integer - 0",
|
||||||
"/string - string - \"string\"",
|
"/array/1 - number_integer - 1",
|
||||||
"/array/0 - number_integer - 0",
|
|
||||||
"/array/1 - number_integer - 1",
|
|
||||||
|
|
||||||
"/array/2/null - null - null",
|
"/array/2/null - null - null",
|
||||||
"/array/2/int - number_integer - -1",
|
"/array/2/int - number_integer - -1",
|
||||||
"/array/2/uint - number_unsigned - 1",
|
"/array/2/uint - number_unsigned - 1",
|
||||||
"/array/2/float - number_float - 1.0",
|
"/array/2/float - number_float - 1.0",
|
||||||
"/array/2/boolean - boolean - true",
|
"/array/2/boolean - boolean - true",
|
||||||
"/array/2/string - string - \"string\"",
|
"/array/2/string - string - \"string\"",
|
||||||
"/array/2/array/0 - number_integer - 0",
|
"/array/2/array/0 - number_integer - 0",
|
||||||
"/array/2/array/1 - number_integer - 1"
|
"/array/2/array/1 - number_integer - 1" };
|
||||||
};
|
|
||||||
|
|
||||||
json.visit(
|
json.visit([&](const json_with_visitor_t::json_pointer& p, const json_with_visitor_t& j) {
|
||||||
[&](const json_with_visitor_t::json_pointer & p,
|
|
||||||
const json_with_visitor_t& j)
|
|
||||||
{
|
|
||||||
std::stringstream str;
|
std::stringstream str;
|
||||||
str << p.to_string() << " - " ;
|
str << p.to_string() << " - ";
|
||||||
using value_t = nlohmann::detail::value_t;
|
using value_t = nlohmann::detail::value_t;
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
{
|
{
|
||||||
@@ -325,12 +316,11 @@ TEST_CASE("JSON Visit Node")
|
|||||||
str << "error";
|
str << "error";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
str << " - " << j.dump();
|
str << " - " << j.dump();
|
||||||
CHECK(json.at(p) == j);
|
CHECK(json.at(p) == j);
|
||||||
INFO(str.str());
|
INFO(str.str());
|
||||||
CHECK(expected.count(str.str()) == 1);
|
CHECK(expected.count(str.str()) == 1);
|
||||||
expected.erase(str.str());
|
expected.erase(str.str());
|
||||||
}
|
});
|
||||||
);
|
|
||||||
CHECK(expected.empty());
|
CHECK(expected.empty());
|
||||||
}
|
}
|
||||||
|
|||||||
+243
-210
@@ -12,7 +12,7 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -125,7 +125,7 @@ struct SaxEventLogger : public nlohmann::json_sax<json>
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> events {};
|
std::vector<std::string> events{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
||||||
@@ -169,7 +169,7 @@ struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template<typename T>
|
||||||
class proxy_iterator
|
class proxy_iterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -177,12 +177,13 @@ class proxy_iterator
|
|||||||
using value_type = typename std::iterator_traits<iterator>::value_type;
|
using value_type = typename std::iterator_traits<iterator>::value_type;
|
||||||
using reference = typename std::iterator_traits<iterator>::reference;
|
using reference = typename std::iterator_traits<iterator>::reference;
|
||||||
using pointer = typename std::iterator_traits<iterator>::pointer;
|
using pointer = typename std::iterator_traits<iterator>::pointer;
|
||||||
using difference_type =
|
using difference_type = typename std::iterator_traits<iterator>::difference_type;
|
||||||
typename std::iterator_traits<iterator>::difference_type;
|
|
||||||
using iterator_category = std::input_iterator_tag;
|
using iterator_category = std::input_iterator_tag;
|
||||||
|
|
||||||
proxy_iterator() = default;
|
proxy_iterator() = default;
|
||||||
explicit proxy_iterator(iterator& it) : m_it(std::addressof(it)) {}
|
explicit proxy_iterator(iterator& it)
|
||||||
|
: m_it(std::addressof(it))
|
||||||
|
{}
|
||||||
|
|
||||||
proxy_iterator& operator++()
|
proxy_iterator& operator++()
|
||||||
{
|
{
|
||||||
@@ -214,7 +215,7 @@ class proxy_iterator
|
|||||||
private:
|
private:
|
||||||
iterator* m_it = nullptr;
|
iterator* m_it = nullptr;
|
||||||
};
|
};
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("deserialization")
|
TEST_CASE("deserialization")
|
||||||
{
|
{
|
||||||
@@ -230,18 +231,22 @@ TEST_CASE("deserialization")
|
|||||||
ss3 << R"(["foo",1,2,3,false,{"one":1}])";
|
ss3 << R"(["foo",1,2,3,false,{"one":1}])";
|
||||||
json j = json::parse(ss1);
|
json j = json::parse(ss1);
|
||||||
CHECK(json::accept(ss2));
|
CHECK(json::accept(ss2));
|
||||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK(j == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(ss3, &l));
|
CHECK(json::sax_parse(ss3, &l));
|
||||||
CHECK(l.events.size() == 11);
|
CHECK(l.events.size() == 11);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"string(foo)",
|
||||||
"start_array()", "string(foo)", "number_unsigned(1)",
|
"number_unsigned(1)",
|
||||||
"number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
|
"number_unsigned(2)",
|
||||||
"start_object()", "key(one)", "number_unsigned(1)",
|
"number_unsigned(3)",
|
||||||
"end_object()", "end_array()"
|
"boolean(false)",
|
||||||
}));
|
"start_object()",
|
||||||
|
"key(one)",
|
||||||
|
"number_unsigned(1)",
|
||||||
|
"end_object()",
|
||||||
|
"end_array()" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string literal")
|
SECTION("string literal")
|
||||||
@@ -249,18 +254,22 @@ TEST_CASE("deserialization")
|
|||||||
const auto* s = R"(["foo",1,2,3,false,{"one":1}])";
|
const auto* s = R"(["foo",1,2,3,false,{"one":1}])";
|
||||||
json j = json::parse(s);
|
json j = json::parse(s);
|
||||||
CHECK(json::accept(s));
|
CHECK(json::accept(s));
|
||||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK(j == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(s, &l));
|
CHECK(json::sax_parse(s, &l));
|
||||||
CHECK(l.events.size() == 11);
|
CHECK(l.events.size() == 11);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"string(foo)",
|
||||||
"start_array()", "string(foo)", "number_unsigned(1)",
|
"number_unsigned(1)",
|
||||||
"number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
|
"number_unsigned(2)",
|
||||||
"start_object()", "key(one)", "number_unsigned(1)",
|
"number_unsigned(3)",
|
||||||
"end_object()", "end_array()"
|
"boolean(false)",
|
||||||
}));
|
"start_object()",
|
||||||
|
"key(one)",
|
||||||
|
"number_unsigned(1)",
|
||||||
|
"end_object()",
|
||||||
|
"end_array()" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string_t")
|
SECTION("string_t")
|
||||||
@@ -268,18 +277,22 @@ TEST_CASE("deserialization")
|
|||||||
json::string_t const s = R"(["foo",1,2,3,false,{"one":1}])";
|
json::string_t const s = R"(["foo",1,2,3,false,{"one":1}])";
|
||||||
json j = json::parse(s);
|
json j = json::parse(s);
|
||||||
CHECK(json::accept(s));
|
CHECK(json::accept(s));
|
||||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK(j == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(s, &l));
|
CHECK(json::sax_parse(s, &l));
|
||||||
CHECK(l.events.size() == 11);
|
CHECK(l.events.size() == 11);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"string(foo)",
|
||||||
"start_array()", "string(foo)", "number_unsigned(1)",
|
"number_unsigned(1)",
|
||||||
"number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
|
"number_unsigned(2)",
|
||||||
"start_object()", "key(one)", "number_unsigned(1)",
|
"number_unsigned(3)",
|
||||||
"end_object()", "end_array()"
|
"boolean(false)",
|
||||||
}));
|
"start_object()",
|
||||||
|
"key(one)",
|
||||||
|
"number_unsigned(1)",
|
||||||
|
"end_object()",
|
||||||
|
"end_array()" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator<<")
|
SECTION("operator<<")
|
||||||
@@ -288,7 +301,7 @@ TEST_CASE("deserialization")
|
|||||||
ss << R"(["foo",1,2,3,false,{"one":1}])";
|
ss << R"(["foo",1,2,3,false,{"one":1}])";
|
||||||
json j;
|
json j;
|
||||||
j << ss;
|
j << ss;
|
||||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK(j == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator>>")
|
SECTION("operator>>")
|
||||||
@@ -297,12 +310,12 @@ TEST_CASE("deserialization")
|
|||||||
ss << R"(["foo",1,2,3,false,{"one":1}])";
|
ss << R"(["foo",1,2,3,false,{"one":1}])";
|
||||||
json j;
|
json j;
|
||||||
ss >> j;
|
ss >> j;
|
||||||
CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK(j == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("user-defined string literal")
|
SECTION("user-defined string literal")
|
||||||
{
|
{
|
||||||
CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}}));
|
CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({ "foo", 1, 2, 3, false, { { "one", 1 } } }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,7 +333,10 @@ TEST_CASE("deserialization")
|
|||||||
ss5 << R"(["foo",1,2,3,false,{"one":1})";
|
ss5 << R"(["foo",1,2,3,false,{"one":1})";
|
||||||
|
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(ss1), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(ss1),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK(!json::accept(ss3));
|
CHECK(!json::accept(ss3));
|
||||||
|
|
||||||
json j_error;
|
json j_error;
|
||||||
@@ -330,20 +346,27 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(ss5, &l));
|
CHECK(!json::sax_parse(ss5, &l));
|
||||||
CHECK(l.events.size() == 11);
|
CHECK(l.events.size() == 11);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"string(foo)",
|
||||||
"start_array()", "string(foo)", "number_unsigned(1)",
|
"number_unsigned(1)",
|
||||||
"number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
|
"number_unsigned(2)",
|
||||||
"start_object()", "key(one)", "number_unsigned(1)",
|
"number_unsigned(3)",
|
||||||
"end_object()", "parse_error(29)"
|
"boolean(false)",
|
||||||
}));
|
"start_object()",
|
||||||
|
"key(one)",
|
||||||
|
"number_unsigned(1)",
|
||||||
|
"end_object()",
|
||||||
|
"parse_error(29)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json::string_t const s = R"(["foo",1,2,3,false,{"one":1})";
|
json::string_t const s = R"(["foo",1,2,3,false,{"one":1})";
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(s), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(s),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK(!json::accept(s));
|
CHECK(!json::accept(s));
|
||||||
|
|
||||||
json j_error;
|
json j_error;
|
||||||
@@ -353,13 +376,17 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(s, &l));
|
CHECK(!json::sax_parse(s, &l));
|
||||||
CHECK(l.events.size() == 11);
|
CHECK(l.events.size() == 11);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"string(foo)",
|
||||||
"start_array()", "string(foo)", "number_unsigned(1)",
|
"number_unsigned(1)",
|
||||||
"number_unsigned(2)", "number_unsigned(3)", "boolean(false)",
|
"number_unsigned(2)",
|
||||||
"start_object()", "key(one)", "number_unsigned(1)",
|
"number_unsigned(3)",
|
||||||
"end_object()", "parse_error(29)"
|
"boolean(false)",
|
||||||
}));
|
"start_object()",
|
||||||
|
"key(one)",
|
||||||
|
"number_unsigned(1)",
|
||||||
|
"end_object()",
|
||||||
|
"parse_error(29)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator<<")
|
SECTION("operator<<")
|
||||||
@@ -367,7 +394,10 @@ TEST_CASE("deserialization")
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << R"(["foo",1,2,3,false,{"one":1})";
|
ss << R"(["foo",1,2,3,false,{"one":1})";
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
j << ss,
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'",
|
||||||
|
json::parse_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operator>>")
|
SECTION("operator>>")
|
||||||
@@ -375,12 +405,18 @@ TEST_CASE("deserialization")
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << R"(["foo",1,2,3,false,{"one":1})";
|
ss << R"(["foo",1,2,3,false,{"one":1})";
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
ss >> j,
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'",
|
||||||
|
json::parse_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("user-defined string literal")
|
SECTION("user-defined string literal")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
"[\"foo\",1,2,3,false,{\"one\":1}"_json,
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'",
|
||||||
|
json::parse_error&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -390,43 +426,43 @@ TEST_CASE("deserialization")
|
|||||||
{
|
{
|
||||||
SECTION("from std::vector")
|
SECTION("from std::vector")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> const v = {'t', 'r', 'u', 'e'};
|
std::vector<uint8_t> const v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::array")
|
SECTION("from std::array")
|
||||||
{
|
{
|
||||||
std::array<uint8_t, 5> const v { {'t', 'r', 'u', 'e'} };
|
std::array<uint8_t, 5> const v{ { 't', 'r', 'u', 'e' } };
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from array")
|
SECTION("from array")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
uint8_t v[] = { 't', 'r', 'u', 'e' }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from chars")
|
SECTION("from chars")
|
||||||
{
|
{
|
||||||
auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory)
|
auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
v[0] = 't';
|
v[0] = 't';
|
||||||
v[1] = 'r';
|
v[1] = 'r';
|
||||||
v[2] = 'u';
|
v[2] = 'u';
|
||||||
@@ -438,33 +474,33 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
|
|
||||||
delete[] v; // NOLINT(cppcoreguidelines-owning-memory)
|
delete[] v; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::string")
|
SECTION("from std::string")
|
||||||
{
|
{
|
||||||
std::string const v = {'t', 'r', 'u', 'e'};
|
std::string const v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::initializer_list")
|
SECTION("from std::initializer_list")
|
||||||
{
|
{
|
||||||
std::initializer_list<uint8_t> const v = {'t', 'r', 'u', 'e'};
|
std::initializer_list<uint8_t> const v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("empty container")
|
SECTION("empty container")
|
||||||
@@ -477,7 +513,7 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(v, &l));
|
CHECK(!json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(1)" }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -485,75 +521,74 @@ TEST_CASE("deserialization")
|
|||||||
{
|
{
|
||||||
SECTION("from std::vector")
|
SECTION("from std::vector")
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
|
std::vector<uint8_t> v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::array")
|
SECTION("from std::array")
|
||||||
{
|
{
|
||||||
std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
|
std::array<uint8_t, 5> v{ { 't', 'r', 'u', 'e' } };
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from array")
|
SECTION("from array")
|
||||||
{
|
{
|
||||||
uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
uint8_t v[] = { 't', 'r', 'u', 'e' }; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::string")
|
SECTION("from std::string")
|
||||||
{
|
{
|
||||||
std::string v = {'t', 'r', 'u', 'e'};
|
std::string v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::initializer_list")
|
SECTION("from std::initializer_list")
|
||||||
{
|
{
|
||||||
std::initializer_list<uint8_t> const v = {'t', 'r', 'u', 'e'};
|
std::initializer_list<uint8_t> const v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("from std::valarray")
|
SECTION("from std::valarray")
|
||||||
{
|
{
|
||||||
std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
|
std::valarray<uint8_t> v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
CHECK(json::parse(std::begin(v), std::end(v)) == json(true));
|
||||||
CHECK(json::accept(std::begin(v), std::end(v)));
|
CHECK(json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("with empty range")
|
SECTION("with empty range")
|
||||||
@@ -566,7 +601,7 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(1)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(1)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("iterator_input_adapter advances iterators correctly")
|
SECTION("iterator_input_adapter advances iterators correctly")
|
||||||
@@ -585,8 +620,7 @@ TEST_CASE("deserialization")
|
|||||||
json j;
|
json j;
|
||||||
json_sax_dom_parser<json> sax(j, true);
|
json_sax_dom_parser<json> sax(j, true);
|
||||||
|
|
||||||
CHECK(json::sax_parse(proxy(first), proxy(last), &sax,
|
CHECK(json::sax_parse(proxy(first), proxy(last), &sax, input_format_t::json, false));
|
||||||
input_format_t::json, false));
|
|
||||||
CHECK(j.dump() == str1);
|
CHECK(j.dump() == str1);
|
||||||
CHECK(std::string(first, last) == str2);
|
CHECK(std::string(first, last) == str2);
|
||||||
}
|
}
|
||||||
@@ -597,7 +631,7 @@ TEST_CASE("deserialization")
|
|||||||
{
|
{
|
||||||
SECTION("case 1")
|
SECTION("case 1")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 9> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}};
|
std::array<std::uint8_t, 9> v = { { '\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u' } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -609,12 +643,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(10)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(10)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 2")
|
SECTION("case 2")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 10> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}};
|
std::array<std::uint8_t, 10> v = { { '\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1' } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -626,12 +660,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(11)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(11)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 3")
|
SECTION("case 3")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}};
|
std::array<std::uint8_t, 17> v = { { '\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1' } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -643,12 +677,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(18)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 4")
|
SECTION("case 4")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}};
|
std::array<std::uint8_t, 17> v = { { '\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\' } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -660,12 +694,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(18)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(18)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 5")
|
SECTION("case 5")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 3> v = {{'\"', 0x7F, 0xC1}};
|
std::array<std::uint8_t, 3> v = { { '\"', 0x7F, 0xC1 } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -677,14 +711,17 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(3)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(3)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 6")
|
SECTION("case 6")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0x7F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xDF, 0x7F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(std::begin(v), std::end(v)),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
|
|
||||||
json j_error;
|
json j_error;
|
||||||
@@ -694,12 +731,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 7")
|
SECTION("case 7")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0xC0}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xDF, 0xC0 } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -711,12 +748,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 8")
|
SECTION("case 8")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xE0, 0x9F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xE0, 0x9F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -728,12 +765,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 9")
|
SECTION("case 9")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xEF, 0xC0}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xEF, 0xC0 } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -745,12 +782,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 10")
|
SECTION("case 10")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xED, 0x7F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xED, 0x7F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -762,12 +799,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 11")
|
SECTION("case 11")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0x8F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xF0, 0x8F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -779,12 +816,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 12")
|
SECTION("case 12")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0xC0}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xF0, 0xC0 } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -796,12 +833,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 13")
|
SECTION("case 13")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0x7F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xF3, 0x7F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -813,12 +850,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 14")
|
SECTION("case 14")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0xC0}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xF3, 0xC0 } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -830,12 +867,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 15")
|
SECTION("case 15")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF4, 0x7F}};
|
std::array<std::uint8_t, 4> v = { { '\"', 0x7F, 0xF4, 0x7F } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -847,12 +884,12 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"parse_error(4)"}));
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("case 16")
|
SECTION("case 16")
|
||||||
{
|
{
|
||||||
std::array<std::uint8_t, 6> v = {{'{', '\"', '\"', ':', '1', '1'}};
|
std::array<std::uint8_t, 6> v = { { '{', '\"', '\"', ':', '1', '1' } };
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&);
|
||||||
CHECK(!json::accept(std::begin(v), std::end(v)));
|
CHECK(!json::accept(std::begin(v), std::end(v)));
|
||||||
@@ -864,11 +901,7 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
CHECK(!json::sax_parse(std::begin(v), std::end(v), &l));
|
||||||
CHECK(l.events.size() == 4);
|
CHECK(l.events.size() == 4);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "start_object()", "key()", "number_unsigned(11)", "parse_error(7)" }));
|
||||||
{
|
|
||||||
"start_object()", "key()", "number_unsigned(11)",
|
|
||||||
"parse_error(7)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -880,17 +913,20 @@ TEST_CASE("deserialization")
|
|||||||
SECTION("BOM only")
|
SECTION("BOM only")
|
||||||
{
|
{
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(bom), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(bom),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(std::istringstream(bom)),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(!json::sax_parse(bom, &l));
|
CHECK(!json::sax_parse(bom, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "parse_error(4)" }));
|
||||||
{
|
|
||||||
"parse_error(4)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("BOM and content")
|
SECTION("BOM and content")
|
||||||
@@ -903,61 +939,55 @@ TEST_CASE("deserialization")
|
|||||||
CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
|
CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1));
|
||||||
CHECK(json::sax_parse(bom + "1", &l2));
|
CHECK(json::sax_parse(bom + "1", &l2));
|
||||||
CHECK(l1.events.size() == 1);
|
CHECK(l1.events.size() == 1);
|
||||||
CHECK(l1.events == std::vector<std::string>(
|
CHECK(l1.events == std::vector<std::string>({ "number_unsigned(1)" }));
|
||||||
{
|
|
||||||
"number_unsigned(1)"
|
|
||||||
}));
|
|
||||||
CHECK(l2.events.size() == 1);
|
CHECK(l2.events.size() == 1);
|
||||||
CHECK(l2.events == std::vector<std::string>(
|
CHECK(l2.events == std::vector<std::string>({ "number_unsigned(1)" }));
|
||||||
{
|
|
||||||
"number_unsigned(1)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("2 byte of BOM")
|
SECTION("2 byte of BOM")
|
||||||
{
|
{
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 2)), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(bom.substr(0, 2)),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(std::istringstream(bom.substr(0, 2))),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
SaxEventLogger l1;
|
SaxEventLogger l1;
|
||||||
SaxEventLogger l2;
|
SaxEventLogger l2;
|
||||||
CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
|
CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1));
|
||||||
CHECK(!json::sax_parse(bom.substr(0, 2), &l2));
|
CHECK(!json::sax_parse(bom.substr(0, 2), &l2));
|
||||||
CHECK(l1.events.size() == 1);
|
CHECK(l1.events.size() == 1);
|
||||||
CHECK(l1.events == std::vector<std::string>(
|
CHECK(l1.events == std::vector<std::string>({ "parse_error(3)" }));
|
||||||
{
|
|
||||||
"parse_error(3)"
|
|
||||||
}));
|
|
||||||
CHECK(l2.events.size() == 1);
|
CHECK(l2.events.size() == 1);
|
||||||
CHECK(l2.events == std::vector<std::string>(
|
CHECK(l2.events == std::vector<std::string>({ "parse_error(3)" }));
|
||||||
{
|
|
||||||
"parse_error(3)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("1 byte of BOM")
|
SECTION("1 byte of BOM")
|
||||||
{
|
{
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 1)), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(bom.substr(0, 1)),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(std::istringstream(bom.substr(0, 1))),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
SaxEventLogger l1;
|
SaxEventLogger l1;
|
||||||
SaxEventLogger l2;
|
SaxEventLogger l2;
|
||||||
CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
|
CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1));
|
||||||
CHECK(!json::sax_parse(bom.substr(0, 1), &l2));
|
CHECK(!json::sax_parse(bom.substr(0, 1), &l2));
|
||||||
CHECK(l1.events.size() == 1);
|
CHECK(l1.events.size() == 1);
|
||||||
CHECK(l1.events == std::vector<std::string>(
|
CHECK(l1.events == std::vector<std::string>({ "parse_error(2)" }));
|
||||||
{
|
|
||||||
"parse_error(2)"
|
|
||||||
}));
|
|
||||||
CHECK(l2.events.size() == 1);
|
CHECK(l2.events.size() == 1);
|
||||||
CHECK(l2.events == std::vector<std::string>(
|
CHECK(l2.events == std::vector<std::string>({ "parse_error(2)" }));
|
||||||
{
|
|
||||||
"parse_error(2)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("variations")
|
SECTION("variations")
|
||||||
@@ -989,10 +1019,7 @@ TEST_CASE("deserialization")
|
|||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(s + "null", &l));
|
CHECK(json::sax_parse(s + "null", &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "null()" }));
|
||||||
{
|
|
||||||
"null()"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -1007,24 +1034,15 @@ TEST_CASE("deserialization")
|
|||||||
|
|
||||||
if (i0 != 0)
|
if (i0 != 0)
|
||||||
{
|
{
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "parse_error(1)" }));
|
||||||
{
|
|
||||||
"parse_error(1)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
else if (i1 != 0)
|
else if (i1 != 0)
|
||||||
{
|
{
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "parse_error(2)" }));
|
||||||
{
|
|
||||||
"parse_error(2)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CHECK(l.events == std::vector<std::string>(
|
CHECK(l.events == std::vector<std::string>({ "parse_error(3)" }));
|
||||||
{
|
|
||||||
"parse_error(3)"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1054,38 +1072,47 @@ TEST_CASE("deserialization")
|
|||||||
|
|
||||||
json::sax_parse(s, &default_logger);
|
json::sax_parse(s, &default_logger);
|
||||||
CHECK(default_logger.events.size() == 14);
|
CHECK(default_logger.events.size() == 14);
|
||||||
CHECK(default_logger.events == std::vector<std::string>(
|
CHECK(default_logger.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"number_unsigned(1)",
|
||||||
"start_array()", "number_unsigned(1)", "start_array()",
|
"start_array()",
|
||||||
"string(string)", "number_float(43.12)", "end_array()", "null()",
|
"string(string)",
|
||||||
"start_object()", "key(key1)", "boolean(true)", "key(key2)",
|
"number_float(43.12)",
|
||||||
"boolean(false)", "end_object()", "end_array()"
|
"end_array()",
|
||||||
}));
|
"null()",
|
||||||
|
"start_object()",
|
||||||
|
"key(key1)",
|
||||||
|
"boolean(true)",
|
||||||
|
"key(key2)",
|
||||||
|
"boolean(false)",
|
||||||
|
"end_object()",
|
||||||
|
"end_array()" }));
|
||||||
|
|
||||||
json::sax_parse(s, &exit_after_start_object);
|
json::sax_parse(s, &exit_after_start_object);
|
||||||
CHECK(exit_after_start_object.events.size() == 8);
|
CHECK(exit_after_start_object.events.size() == 8);
|
||||||
CHECK(exit_after_start_object.events == std::vector<std::string>(
|
CHECK(exit_after_start_object.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"number_unsigned(1)",
|
||||||
"start_array()", "number_unsigned(1)", "start_array()",
|
"start_array()",
|
||||||
"string(string)", "number_float(43.12)", "end_array()", "null()",
|
"string(string)",
|
||||||
"start_object()"
|
"number_float(43.12)",
|
||||||
}));
|
"end_array()",
|
||||||
|
"null()",
|
||||||
|
"start_object()" }));
|
||||||
|
|
||||||
json::sax_parse(s, &exit_after_key);
|
json::sax_parse(s, &exit_after_key);
|
||||||
CHECK(exit_after_key.events.size() == 9);
|
CHECK(exit_after_key.events.size() == 9);
|
||||||
CHECK(exit_after_key.events == std::vector<std::string>(
|
CHECK(exit_after_key.events == std::vector<std::string>({ "start_array()",
|
||||||
{
|
"number_unsigned(1)",
|
||||||
"start_array()", "number_unsigned(1)", "start_array()",
|
"start_array()",
|
||||||
"string(string)", "number_float(43.12)", "end_array()", "null()",
|
"string(string)",
|
||||||
"start_object()", "key(key1)"
|
"number_float(43.12)",
|
||||||
}));
|
"end_array()",
|
||||||
|
"null()",
|
||||||
|
"start_object()",
|
||||||
|
"key(key1)" }));
|
||||||
|
|
||||||
json::sax_parse(s, &exit_after_start_array);
|
json::sax_parse(s, &exit_after_start_array);
|
||||||
CHECK(exit_after_start_array.events.size() == 1);
|
CHECK(exit_after_start_array.events.size() == 1);
|
||||||
CHECK(exit_after_start_array.events == std::vector<std::string>(
|
CHECK(exit_after_start_array.events == std::vector<std::string>({ "start_array()" }));
|
||||||
{
|
|
||||||
"start_array()"
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JSON Lines")
|
SECTION("JSON Lines")
|
||||||
@@ -1131,29 +1158,37 @@ TEST_CASE("deserialization")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T,
|
TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)",
|
||||||
char, unsigned char, signed char,
|
T,
|
||||||
|
char,
|
||||||
|
unsigned char,
|
||||||
|
signed char,
|
||||||
wchar_t,
|
wchar_t,
|
||||||
char16_t, char32_t,
|
char16_t,
|
||||||
std::uint8_t, std::int8_t,
|
char32_t,
|
||||||
std::int16_t, std::uint16_t,
|
std::uint8_t,
|
||||||
std::int32_t, std::uint32_t)
|
std::int8_t,
|
||||||
|
std::int16_t,
|
||||||
|
std::uint16_t,
|
||||||
|
std::int32_t,
|
||||||
|
std::uint32_t)
|
||||||
{
|
{
|
||||||
std::vector<T> const v = {'t', 'r', 'u', 'e'};
|
std::vector<T> const v = { 't', 'r', 'u', 'e' };
|
||||||
CHECK(json::parse(v) == json(true));
|
CHECK(json::parse(v) == json(true));
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
SaxEventLogger l;
|
SaxEventLogger l;
|
||||||
CHECK(json::sax_parse(v, &l));
|
CHECK(json::sax_parse(v, &l));
|
||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
CHECK(l.events == std::vector<std::string>({"boolean(true)"}));
|
CHECK(l.events == std::vector<std::string>({ "boolean(true)" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T,
|
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, char, unsigned char, std::uint8_t)
|
||||||
char, unsigned char, std::uint8_t)
|
|
||||||
{
|
{
|
||||||
// a star emoji
|
// a star emoji
|
||||||
std::vector<T> const v = {'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'};
|
std::vector<T> const v = {
|
||||||
|
'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'
|
||||||
|
};
|
||||||
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
@@ -1162,11 +1197,10 @@ TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T,
|
|||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T,
|
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, char16_t, std::uint16_t)
|
||||||
char16_t, std::uint16_t)
|
|
||||||
{
|
{
|
||||||
// a star emoji
|
// a star emoji
|
||||||
std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
|
std::vector<T> const v = { static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"') };
|
||||||
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
@@ -1175,11 +1209,10 @@ TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T,
|
|||||||
CHECK(l.events.size() == 1);
|
CHECK(l.events.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T,
|
TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T, char32_t, std::uint32_t)
|
||||||
char32_t, std::uint32_t)
|
|
||||||
{
|
{
|
||||||
// a star emoji
|
// a star emoji
|
||||||
std::vector<T> const v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')};
|
std::vector<T> const v = { static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"') };
|
||||||
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\"");
|
||||||
CHECK(json::accept(v));
|
CHECK(json::accept(v));
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ TEST_CASE("Better diagnostics")
|
|||||||
json j;
|
json j;
|
||||||
j["a"]["b"]["c"] = 1;
|
j["a"]["b"]["c"] = 1;
|
||||||
std::string s;
|
std::string s;
|
||||||
CHECK_THROWS_WITH_AS(s = j["a"]["b"]["c"].get<std::string>(), "[json.exception.type_error.302] (/a/b/c) type must be string, but is number", json::type_error);
|
CHECK_THROWS_WITH_AS(s = j["a"]["b"]["c"].get<std::string>(),
|
||||||
|
"[json.exception.type_error.302] (/a/b/c) type must be string, but is number",
|
||||||
|
json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing key")
|
SECTION("missing key")
|
||||||
@@ -53,14 +55,18 @@ TEST_CASE("Better diagnostics")
|
|||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
j["array"][4] = true;
|
j["array"][4] = true;
|
||||||
CHECK_THROWS_WITH_AS(j["array"][4][5], "[json.exception.type_error.305] (/array/4) cannot use operator[] with a numeric argument with boolean", json::type_error);
|
CHECK_THROWS_WITH_AS(j["array"][4][5],
|
||||||
|
"[json.exception.type_error.305] (/array/4) cannot use operator[] with a numeric argument with boolean",
|
||||||
|
json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("wrong iterator")
|
SECTION("wrong iterator")
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
j["array"] = json::array();
|
j["array"] = json::array();
|
||||||
CHECK_THROWS_WITH_AS(j["array"].erase(j.begin()), "[json.exception.invalid_iterator.202] (/array) iterator does not fit current value", json::invalid_iterator);
|
CHECK_THROWS_WITH_AS(j["array"].erase(j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.202] (/array) iterator does not fit current value",
|
||||||
|
json::invalid_iterator);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("JSON Pointer escaping")
|
SECTION("JSON Pointer escaping")
|
||||||
@@ -68,21 +74,28 @@ TEST_CASE("Better diagnostics")
|
|||||||
json j;
|
json j;
|
||||||
j["a/b"]["m~n"] = 1;
|
j["a/b"]["m~n"] = 1;
|
||||||
std::string s;
|
std::string s;
|
||||||
CHECK_THROWS_WITH_AS(s = j["a/b"]["m~n"].get<std::string>(), "[json.exception.type_error.302] (/a~1b/m~0n) type must be string, but is number", json::type_error);
|
CHECK_THROWS_WITH_AS(s = j["a/b"]["m~n"].get<std::string>(),
|
||||||
|
"[json.exception.type_error.302] (/a~1b/m~0n) type must be string, but is number",
|
||||||
|
json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Parse error")
|
SECTION("Parse error")
|
||||||
{
|
{
|
||||||
json _;
|
json _;
|
||||||
CHECK_THROWS_WITH_AS(_ = json::parse(""), "[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON", json::parse_error);
|
CHECK_THROWS_WITH_AS(
|
||||||
|
_ = json::parse(""),
|
||||||
|
"[json.exception.parse_error.101] parse error at line 1, column 1: attempting to parse an empty input; check that your input string or stream contains the expected JSON",
|
||||||
|
json::parse_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Wrong type in update()")
|
SECTION("Wrong type in update()")
|
||||||
{
|
{
|
||||||
json j = {{"foo", "bar"}};
|
json j = { { "foo", "bar" } };
|
||||||
json k = {{"bla", 1}};
|
json k = { { "bla", 1 } };
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j.update(k["bla"].begin(), k["bla"].end()), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
|
CHECK_THROWS_WITH_AS(j.update(k["bla"].begin(), k["bla"].end()),
|
||||||
|
"[json.exception.type_error.312] (/bla) cannot use update() with number",
|
||||||
|
json::type_error);
|
||||||
CHECK_THROWS_WITH_AS(j.update(k["bla"]), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
|
CHECK_THROWS_WITH_AS(j.update(k["bla"]), "[json.exception.type_error.312] (/bla) cannot use update() with number", json::type_error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,14 +104,14 @@ TEST_CASE("Regression tests for extended diagnostics")
|
|||||||
{
|
{
|
||||||
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
|
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562#pullrequestreview-574858448")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH_AS(json({"0", "0"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
|
CHECK_THROWS_WITH_AS(json({ "0", "0" })[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
|
||||||
CHECK_THROWS_WITH_AS(json({"0", "1"})[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
|
CHECK_THROWS_WITH_AS(json({ "0", "1" })[1].get<int>(), "[json.exception.type_error.302] (/1) type must be number, but is string", json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
|
SECTION("Regression test for https://github.com/nlohmann/json/pull/2562/files/380a613f2b5d32425021129cd1f371ddcfd54ddf#r563259793")
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
j["/foo"] = {1, 2, 3};
|
j["/foo"] = { 1, 2, 3 };
|
||||||
CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
|
CHECK_THROWS_WITH_AS(j.unflatten(), "[json.exception.type_error.315] (/~1foo) values in object must be primitive", json::type_error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,7 +173,7 @@ TEST_CASE("Regression tests for extended diagnostics")
|
|||||||
// iterator insert(const_iterator pos, const_iterator first, const_iterator last)
|
// iterator insert(const_iterator pos, const_iterator first, const_iterator last)
|
||||||
{
|
{
|
||||||
json j_arr = json::array();
|
json j_arr = json::array();
|
||||||
json j_objects = {json::object(), json::object()};
|
json j_objects = { json::object(), json::object() };
|
||||||
j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
|
j_arr.insert(j_arr.begin(), j_objects.begin(), j_objects.end());
|
||||||
json j_obj = json::object();
|
json j_obj = json::object();
|
||||||
j_obj["key"] = j_arr;
|
j_obj["key"] = j_arr;
|
||||||
|
|||||||
@@ -23,11 +23,13 @@ using json = nlohmann::json;
|
|||||||
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
|
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser<json>(j, false) {}
|
explicit sax_no_exception(json& j)
|
||||||
|
: nlohmann::detail::json_sax_dom_parser<json>(j, false)
|
||||||
|
{}
|
||||||
|
|
||||||
static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
|
static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
|
||||||
{
|
{
|
||||||
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,9 +45,10 @@ TEST_CASE("Tests with disabled exceptions")
|
|||||||
json j;
|
json j;
|
||||||
sax_no_exception sax(j);
|
sax_no_exception sax(j);
|
||||||
|
|
||||||
CHECK (!json::sax_parse("xyz", &sax));
|
CHECK(!json::sax_parse("xyz", &sax));
|
||||||
CHECK(*sax_no_exception::error_string == "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
|
CHECK(*sax_no_exception::error_string ==
|
||||||
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
|
"[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'x'");
|
||||||
|
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json j = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
|
||||||
SECTION("access specified element with bounds checking")
|
SECTION("access specified element with bounds checking")
|
||||||
@@ -30,7 +30,7 @@ TEST_CASE("element access 1")
|
|||||||
CHECK(j.at(4) == json("string"));
|
CHECK(j.at(4) == json("string"));
|
||||||
CHECK(j.at(5) == json(42.23));
|
CHECK(j.at(5) == json(42.23));
|
||||||
CHECK(j.at(6) == json::object());
|
CHECK(j.at(6) == json::object());
|
||||||
CHECK(j.at(7) == json({1, 2, 3}));
|
CHECK(j.at(7) == json({ 1, 2, 3 }));
|
||||||
|
|
||||||
CHECK(j_const.at(0) == json(1));
|
CHECK(j_const.at(0) == json(1));
|
||||||
CHECK(j_const.at(1) == json(1u));
|
CHECK(j_const.at(1) == json(1u));
|
||||||
@@ -39,15 +39,13 @@ TEST_CASE("element access 1")
|
|||||||
CHECK(j_const.at(4) == json("string"));
|
CHECK(j_const.at(4) == json("string"));
|
||||||
CHECK(j_const.at(5) == json(42.23));
|
CHECK(j_const.at(5) == json(42.23));
|
||||||
CHECK(j_const.at(6) == json::object());
|
CHECK(j_const.at(6) == json::object());
|
||||||
CHECK(j_const.at(7) == json({1, 2, 3}));
|
CHECK(j_const.at(7) == json({ 1, 2, 3 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access outside bounds")
|
SECTION("access outside bounds")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH_AS(j.at(8),
|
CHECK_THROWS_WITH_AS(j.at(8), "[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j_const.at(8), "[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j_const.at(8),
|
|
||||||
"[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access on non-array type")
|
SECTION("access on non-array type")
|
||||||
@@ -121,8 +119,8 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
CHECK(j.front() == json(1));
|
CHECK(j.front() == json(1));
|
||||||
CHECK(j_const.front() == json(1));
|
CHECK(j_const.front() == json(1));
|
||||||
CHECK(j.back() == json({1, 2, 3}));
|
CHECK(j.back() == json({ 1, 2, 3 }));
|
||||||
CHECK(j_const.back() == json({1, 2, 3}));
|
CHECK(j_const.back() == json({ 1, 2, 3 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access specified element")
|
SECTION("access specified element")
|
||||||
@@ -136,7 +134,7 @@ TEST_CASE("element access 1")
|
|||||||
CHECK(j[4] == json("string"));
|
CHECK(j[4] == json("string"));
|
||||||
CHECK(j[5] == json(42.23));
|
CHECK(j[5] == json(42.23));
|
||||||
CHECK(j[6] == json::object());
|
CHECK(j[6] == json::object());
|
||||||
CHECK(j[7] == json({1, 2, 3}));
|
CHECK(j[7] == json({ 1, 2, 3 }));
|
||||||
|
|
||||||
CHECK(j_const[0] == json(1));
|
CHECK(j_const[0] == json(1));
|
||||||
CHECK(j_const[1] == json(1u));
|
CHECK(j_const[1] == json(1u));
|
||||||
@@ -145,7 +143,7 @@ TEST_CASE("element access 1")
|
|||||||
CHECK(j_const[4] == json("string"));
|
CHECK(j_const[4] == json("string"));
|
||||||
CHECK(j_const[5] == json(42.23));
|
CHECK(j_const[5] == json(42.23));
|
||||||
CHECK(j_const[6] == json::object());
|
CHECK(j_const[6] == json::object());
|
||||||
CHECK(j_const[7] == json({1, 2, 3}));
|
CHECK(j_const[7] == json({ 1, 2, 3 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("access on non-array type")
|
SECTION("access on non-array type")
|
||||||
@@ -157,14 +155,16 @@ TEST_CASE("element access 1")
|
|||||||
json j_nonarray(json::value_t::null);
|
json j_nonarray(json::value_t::null);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_NOTHROW(j_nonarray[0]);
|
CHECK_NOTHROW(j_nonarray[0]);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with null", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with null",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("implicit transformation to properly filled array")
|
SECTION("implicit transformation to properly filled array")
|
||||||
{
|
{
|
||||||
json j_nonarray;
|
json j_nonarray;
|
||||||
j_nonarray[3] = 42;
|
j_nonarray[3] = 42;
|
||||||
CHECK(j_nonarray == json({nullptr, nullptr, nullptr, 42}));
|
CHECK(j_nonarray == json({ nullptr, nullptr, nullptr, 42 }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,48 +172,72 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::boolean);
|
json j_nonarray(json::value_t::boolean);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with boolean",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("string")
|
SECTION("string")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::string);
|
json j_nonarray(json::value_t::string);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with string", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with string",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with string",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::object);
|
json j_nonarray(json::value_t::object);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with object", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with object",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with object",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (integer)")
|
SECTION("number (integer)")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::number_integer);
|
json j_nonarray(json::value_t::number_integer);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (unsigned)")
|
SECTION("number (unsigned)")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::number_unsigned);
|
json j_nonarray(json::value_t::number_unsigned);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("number (floating-point)")
|
SECTION("number (floating-point)")
|
||||||
{
|
{
|
||||||
json j_nonarray(json::value_t::number_float);
|
json j_nonarray(json::value_t::number_float);
|
||||||
const json j_nonarray_const(j_nonarray);
|
const json j_nonarray_const(j_nonarray);
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
CHECK_THROWS_WITH_AS(j_nonarray[0],
|
||||||
CHECK_THROWS_WITH_AS(j_nonarray_const[0], "[json.exception.type_error.305] cannot use operator[] with a numeric argument with number", json::type_error&);
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
|
CHECK_THROWS_WITH_AS(j_nonarray_const[0],
|
||||||
|
"[json.exception.type_error.305] cannot use operator[] with a numeric argument with number",
|
||||||
|
json::type_error&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -223,47 +247,47 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("remove element by index")
|
SECTION("remove element by index")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(0);
|
jarray.erase(0);
|
||||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(1);
|
jarray.erase(1);
|
||||||
CHECK(jarray == json({1, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(2);
|
jarray.erase(2);
|
||||||
CHECK(jarray == json({1, 1u, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(3);
|
jarray.erase(3);
|
||||||
CHECK(jarray == json({1, 1u, true, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(4);
|
jarray.erase(4);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(5);
|
jarray.erase(5);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, "string", json::object(), { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(6);
|
jarray.erase(6);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, "string", 42.23, { 1, 2, 3 } }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
jarray.erase(7);
|
jarray.erase(7);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object()}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, "string", 42.23, json::object() }));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(8), "[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(jarray.erase(8), "[json.exception.out_of_range.401] array index 8 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -273,15 +297,15 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("erase(begin())")
|
SECTION("erase(begin())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::iterator const it2 = jarray.erase(jarray.begin());
|
json::iterator const it2 = jarray.erase(jarray.begin());
|
||||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(1u));
|
CHECK(*it2 == json(1u));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::const_iterator const it2 = jarray.erase(jarray.cbegin());
|
json::const_iterator const it2 = jarray.erase(jarray.cbegin());
|
||||||
CHECK(jarray == json({1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(1u));
|
CHECK(*it2 == json(1u));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -289,13 +313,13 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("erase(begin(), end())")
|
SECTION("erase(begin(), end())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
|
json::iterator it2 = jarray.erase(jarray.begin(), jarray.end());
|
||||||
CHECK(jarray == json::array());
|
CHECK(jarray == json::array());
|
||||||
CHECK(it2 == jarray.end());
|
CHECK(it2 == jarray.end());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
|
json::const_iterator it2 = jarray.erase(jarray.cbegin(), jarray.cend());
|
||||||
CHECK(jarray == json::array());
|
CHECK(jarray == json::array());
|
||||||
CHECK(it2 == jarray.cend());
|
CHECK(it2 == jarray.cend());
|
||||||
@@ -305,15 +329,15 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("erase(begin(), begin())")
|
SECTION("erase(begin(), begin())")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::iterator const it2 = jarray.erase(jarray.begin(), jarray.begin());
|
json::iterator const it2 = jarray.erase(jarray.begin(), jarray.begin());
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(1));
|
CHECK(*it2 == json(1));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::const_iterator const it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
|
json::const_iterator const it2 = jarray.erase(jarray.cbegin(), jarray.cbegin());
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(1));
|
CHECK(*it2 == json(1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -321,17 +345,17 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("erase at offset")
|
SECTION("erase at offset")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::iterator const it = jarray.begin() + 4;
|
json::iterator const it = jarray.begin() + 4;
|
||||||
json::iterator const it2 = jarray.erase(it);
|
json::iterator const it2 = jarray.erase(it);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(42.23));
|
CHECK(*it2 == json(42.23));
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::const_iterator const it = jarray.cbegin() + 4;
|
json::const_iterator const it = jarray.cbegin() + 4;
|
||||||
json::const_iterator const it2 = jarray.erase(it);
|
json::const_iterator const it2 = jarray.erase(it);
|
||||||
CHECK(jarray == json({1, 1u, true, nullptr, 42.23, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, nullptr, 42.23, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json(42.23));
|
CHECK(*it2 == json(42.23));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -339,15 +363,15 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("erase subrange")
|
SECTION("erase subrange")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::iterator const it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
|
json::iterator const it2 = jarray.erase(jarray.begin() + 3, jarray.begin() + 6);
|
||||||
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json::object());
|
CHECK(*it2 == json::object());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json::const_iterator const it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
|
json::const_iterator const it2 = jarray.erase(jarray.cbegin() + 3, jarray.cbegin() + 6);
|
||||||
CHECK(jarray == json({1, 1u, true, json::object(), {1, 2, 3}}));
|
CHECK(jarray == json({ 1, 1u, true, json::object(), { 1, 2, 3 } }));
|
||||||
CHECK(*it2 == json::object());
|
CHECK(*it2 == json::object());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -355,30 +379,38 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("different arrays")
|
SECTION("different arrays")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json jarray2 = {"foo", "bar"};
|
json jarray2 = { "foo", "bar" };
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin()),
|
||||||
"[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.202] iterator does not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray.begin(), jarray2.end()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray.begin(), jarray2.end()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray.end()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray.end()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray2.end()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.begin(), jarray2.end()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json jarray = {1, 1u, true, nullptr, "string", 42.23, json::object(), {1, 2, 3}};
|
json jarray = { 1, 1u, true, nullptr, "string", 42.23, json::object(), { 1, 2, 3 } };
|
||||||
json const jarray2 = {"foo", "bar"};
|
json const jarray2 = { "foo", "bar" };
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin()),
|
||||||
"[json.exception.invalid_iterator.202] iterator does not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.202] iterator does not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray.cbegin(), jarray2.cend()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray.cbegin(), jarray2.cend()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray.cend()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray.cend()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()),
|
CHECK_THROWS_WITH_AS(jarray.erase(jarray2.cbegin(), jarray2.cend()),
|
||||||
"[json.exception.invalid_iterator.203] iterators do not fit current value", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.203] iterators do not fit current value",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -529,8 +561,7 @@ TEST_CASE("element access 1")
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j;
|
json j;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin()),
|
CHECK_THROWS_WITH_AS(j.erase(j.begin()), "[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
|
||||||
"[json.exception.type_error.307] cannot use erase() with null", json::type_error&);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -617,13 +648,13 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("binary")
|
SECTION("binary")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json::iterator it = j.erase(j.begin());
|
json::iterator it = j.erase(j.begin());
|
||||||
CHECK(j.type() == json::value_t::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
CHECK(it == j.end());
|
CHECK(it == j.end());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json::const_iterator it = j.erase(j.cbegin());
|
json::const_iterator it = j.erase(j.cbegin());
|
||||||
CHECK(j.type() == json::value_t::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
CHECK(it == j.end());
|
CHECK(it == j.end());
|
||||||
@@ -791,13 +822,13 @@ TEST_CASE("element access 1")
|
|||||||
SECTION("binary")
|
SECTION("binary")
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json::iterator it = j.erase(j.begin(), j.end());
|
json::iterator it = j.erase(j.begin(), j.end());
|
||||||
CHECK(j.type() == json::value_t::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
CHECK(it == j.end());
|
CHECK(it == j.end());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = json::binary({1, 2, 3});
|
json j = json::binary({ 1, 2, 3 });
|
||||||
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
json::const_iterator it = j.erase(j.cbegin(), j.cend());
|
||||||
CHECK(j.type() == json::value_t::null);
|
CHECK(j.type() == json::value_t::null);
|
||||||
CHECK(it == j.end());
|
CHECK(it == j.end());
|
||||||
@@ -812,12 +843,16 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j = "foo";
|
json j = "foo";
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = "bar";
|
json j = "bar";
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -826,12 +861,16 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j = false;
|
json j = false;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = true;
|
json j = true;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -840,12 +879,16 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j = 17;
|
json j = 17;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = 17;
|
json j = 17;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -854,12 +897,16 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j = 17u;
|
json j = 17u;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = 17u;
|
json j = 17u;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,12 +915,16 @@ TEST_CASE("element access 1")
|
|||||||
{
|
{
|
||||||
json j = 23.42;
|
json j = 23.42;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.end(), j.end()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.begin(), j.begin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
json j = 23.42;
|
json j = 23.42;
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cend(), j.cend()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()), "[json.exception.invalid_iterator.204] iterators out of range", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.erase(j.cbegin(), j.cbegin()),
|
||||||
|
"[json.exception.invalid_iterator.204] iterators out of range",
|
||||||
|
json::invalid_iterator&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1526
-1327
File diff suppressed because it is too large
Load Diff
+42
-42
@@ -23,42 +23,42 @@ TEST_CASE("hash<nlohmann::json>")
|
|||||||
std::set<std::size_t> hashes;
|
std::set<std::size_t> hashes;
|
||||||
|
|
||||||
// null
|
// null
|
||||||
hashes.insert(std::hash<json> {}(json(nullptr)));
|
hashes.insert(std::hash<json>{}(json(nullptr)));
|
||||||
|
|
||||||
// boolean
|
// boolean
|
||||||
hashes.insert(std::hash<json> {}(json(true)));
|
hashes.insert(std::hash<json>{}(json(true)));
|
||||||
hashes.insert(std::hash<json> {}(json(false)));
|
hashes.insert(std::hash<json>{}(json(false)));
|
||||||
|
|
||||||
// string
|
// string
|
||||||
hashes.insert(std::hash<json> {}(json("")));
|
hashes.insert(std::hash<json>{}(json("")));
|
||||||
hashes.insert(std::hash<json> {}(json("foo")));
|
hashes.insert(std::hash<json>{}(json("foo")));
|
||||||
|
|
||||||
// number
|
// number
|
||||||
hashes.insert(std::hash<json> {}(json(0)));
|
hashes.insert(std::hash<json>{}(json(0)));
|
||||||
hashes.insert(std::hash<json> {}(json(static_cast<unsigned>(0))));
|
hashes.insert(std::hash<json>{}(json(static_cast<unsigned>(0))));
|
||||||
|
|
||||||
hashes.insert(std::hash<json> {}(json(-1)));
|
hashes.insert(std::hash<json>{}(json(-1)));
|
||||||
hashes.insert(std::hash<json> {}(json(0.0)));
|
hashes.insert(std::hash<json>{}(json(0.0)));
|
||||||
hashes.insert(std::hash<json> {}(json(42.23)));
|
hashes.insert(std::hash<json>{}(json(42.23)));
|
||||||
|
|
||||||
// array
|
// array
|
||||||
hashes.insert(std::hash<json> {}(json::array()));
|
hashes.insert(std::hash<json>{}(json::array()));
|
||||||
hashes.insert(std::hash<json> {}(json::array({1, 2, 3})));
|
hashes.insert(std::hash<json>{}(json::array({ 1, 2, 3 })));
|
||||||
|
|
||||||
// object
|
// object
|
||||||
hashes.insert(std::hash<json> {}(json::object()));
|
hashes.insert(std::hash<json>{}(json::object()));
|
||||||
hashes.insert(std::hash<json> {}(json::object({{"foo", "bar"}})));
|
hashes.insert(std::hash<json>{}(json::object({ { "foo", "bar" } })));
|
||||||
|
|
||||||
// binary
|
// binary
|
||||||
hashes.insert(std::hash<json> {}(json::binary({})));
|
hashes.insert(std::hash<json>{}(json::binary({})));
|
||||||
hashes.insert(std::hash<json> {}(json::binary({}, 0)));
|
hashes.insert(std::hash<json>{}(json::binary({}, 0)));
|
||||||
hashes.insert(std::hash<json> {}(json::binary({}, 42)));
|
hashes.insert(std::hash<json>{}(json::binary({}, 42)));
|
||||||
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3})));
|
hashes.insert(std::hash<json>{}(json::binary({ 1, 2, 3 })));
|
||||||
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3}, 0)));
|
hashes.insert(std::hash<json>{}(json::binary({ 1, 2, 3 }, 0)));
|
||||||
hashes.insert(std::hash<json> {}(json::binary({1, 2, 3}, 42)));
|
hashes.insert(std::hash<json>{}(json::binary({ 1, 2, 3 }, 42)));
|
||||||
|
|
||||||
// discarded
|
// discarded
|
||||||
hashes.insert(std::hash<json> {}(json(json::value_t::discarded)));
|
hashes.insert(std::hash<json>{}(json(json::value_t::discarded)));
|
||||||
|
|
||||||
CHECK(hashes.size() == 21);
|
CHECK(hashes.size() == 21);
|
||||||
}
|
}
|
||||||
@@ -72,42 +72,42 @@ TEST_CASE("hash<nlohmann::ordered_json>")
|
|||||||
std::set<std::size_t> hashes;
|
std::set<std::size_t> hashes;
|
||||||
|
|
||||||
// null
|
// null
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(nullptr)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(nullptr)));
|
||||||
|
|
||||||
// boolean
|
// boolean
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(true)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(true)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(false)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(false)));
|
||||||
|
|
||||||
// string
|
// string
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json("")));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json("")));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json("foo")));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json("foo")));
|
||||||
|
|
||||||
// number
|
// number
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(0)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(0)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(static_cast<unsigned>(0))));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(static_cast<unsigned>(0))));
|
||||||
|
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(-1)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(-1)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(0.0)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(0.0)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(42.23)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(42.23)));
|
||||||
|
|
||||||
// array
|
// array
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::array()));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::array()));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::array({1, 2, 3})));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::array({ 1, 2, 3 })));
|
||||||
|
|
||||||
// object
|
// object
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::object()));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::object()));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::object({{"foo", "bar"}})));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::object({ { "foo", "bar" } })));
|
||||||
|
|
||||||
// binary
|
// binary
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({})));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({})));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({}, 0)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({}, 0)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({}, 42)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({}, 42)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3})));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({ 1, 2, 3 })));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3}, 0)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({ 1, 2, 3 }, 0)));
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json::binary({1, 2, 3}, 42)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json::binary({ 1, 2, 3 }, 42)));
|
||||||
|
|
||||||
// discarded
|
// discarded
|
||||||
hashes.insert(std::hash<ordered_json> {}(ordered_json(ordered_json::value_t::discarded)));
|
hashes.insert(std::hash<ordered_json>{}(ordered_json(ordered_json::value_t::discarded)));
|
||||||
|
|
||||||
CHECK(hashes.size() == 21);
|
CHECK(hashes.size() == 21);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,9 +11,9 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
|
#include "make_test_data_available.hpp"
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include "make_test_data_available.hpp"
|
|
||||||
|
|
||||||
TEST_CASE("object inspection")
|
TEST_CASE("object inspection")
|
||||||
{
|
{
|
||||||
@@ -21,7 +21,7 @@ TEST_CASE("object inspection")
|
|||||||
{
|
{
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j {{"foo", 1}, {"bar", false}};
|
json const j{ { "foo", 1 }, { "bar", false } };
|
||||||
CHECK(!j.is_null());
|
CHECK(!j.is_null());
|
||||||
CHECK(!j.is_boolean());
|
CHECK(!j.is_boolean());
|
||||||
CHECK(!j.is_number());
|
CHECK(!j.is_number());
|
||||||
@@ -39,7 +39,7 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j {"foo", 1, 1u, 42.23, false};
|
json const j{ "foo", 1, 1u, 42.23, false };
|
||||||
CHECK(!j.is_null());
|
CHECK(!j.is_null());
|
||||||
CHECK(!j.is_boolean());
|
CHECK(!j.is_boolean());
|
||||||
CHECK(!j.is_number());
|
CHECK(!j.is_number());
|
||||||
@@ -202,12 +202,12 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("serialization")
|
SECTION("serialization")
|
||||||
{
|
{
|
||||||
json const j {{"object", json::object()}, {"array", {1, 2, 3, 4}}, {"number", 42}, {"boolean", false}, {"null", nullptr}, {"string", "Hello world"} };
|
json const j{ { "object", json::object() }, { "array", { 1, 2, 3, 4 } }, { "number", 42 },
|
||||||
|
{ "boolean", false }, { "null", nullptr }, { "string", "Hello world" } };
|
||||||
|
|
||||||
SECTION("no indent / indent=-1")
|
SECTION("no indent / indent=-1")
|
||||||
{
|
{
|
||||||
CHECK(j.dump() ==
|
CHECK(j.dump() == "{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
|
||||||
"{\"array\":[1,2,3,4],\"boolean\":false,\"null\":null,\"number\":42,\"object\":{},\"string\":\"Hello world\"}");
|
|
||||||
|
|
||||||
CHECK(j.dump() == j.dump(-1));
|
CHECK(j.dump() == j.dump(-1));
|
||||||
}
|
}
|
||||||
@@ -220,14 +220,16 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("indent=1, space='\t'")
|
SECTION("indent=1, space='\t'")
|
||||||
{
|
{
|
||||||
CHECK(j.dump(1, '\t') ==
|
CHECK(
|
||||||
"{\n\t\"array\": [\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t],\n\t\"boolean\": false,\n\t\"null\": null,\n\t\"number\": 42,\n\t\"object\": {},\n\t\"string\": \"Hello world\"\n}");
|
j.dump(1, '\t') ==
|
||||||
|
"{\n\t\"array\": [\n\t\t1,\n\t\t2,\n\t\t3,\n\t\t4\n\t],\n\t\"boolean\": false,\n\t\"null\": null,\n\t\"number\": 42,\n\t\"object\": {},\n\t\"string\": \"Hello world\"\n}");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("indent=4")
|
SECTION("indent=4")
|
||||||
{
|
{
|
||||||
CHECK(j.dump(4) ==
|
CHECK(
|
||||||
"{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
|
j.dump(4) ==
|
||||||
|
"{\n \"array\": [\n 1,\n 2,\n 3,\n 4\n ],\n \"boolean\": false,\n \"null\": null,\n \"number\": 42,\n \"object\": {},\n \"string\": \"Hello world\"\n}");
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("indent=x")
|
SECTION("indent=x")
|
||||||
@@ -241,7 +243,7 @@ TEST_CASE("object inspection")
|
|||||||
// inside the dump() function
|
// inside the dump() function
|
||||||
CHECK(j.dump(1024).size() == 15472);
|
CHECK(j.dump(1024).size() == 15472);
|
||||||
|
|
||||||
const auto binary = json::binary({1, 2, 3}, 128);
|
const auto binary = json::binary({ 1, 2, 3 }, 128);
|
||||||
CHECK(binary.dump(1024).size() == 2086);
|
CHECK(binary.dump(1024).size() == 2086);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -291,8 +293,7 @@ TEST_CASE("object inspection")
|
|||||||
json const value = json::parse(f_unescaped);
|
json const value = json::parse(f_unescaped);
|
||||||
std::string text = value.dump(4, ' ', true);
|
std::string text = value.dump(4, ' ', true);
|
||||||
|
|
||||||
std::string expected((std::istreambuf_iterator<char>(f_escaped)),
|
std::string expected((std::istreambuf_iterator<char>(f_escaped)), std::istreambuf_iterator<char>());
|
||||||
std::istreambuf_iterator<char>());
|
|
||||||
CHECK(text == expected);
|
CHECK(text == expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -328,9 +329,7 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("round trips")
|
SECTION("round trips")
|
||||||
{
|
{
|
||||||
for (const auto& s :
|
for (const auto& s : { "3.141592653589793", "1000000000000000010E5" })
|
||||||
{"3.141592653589793", "1000000000000000010E5"
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
json const j1 = json::parse(s);
|
json const j1 = json::parse(s);
|
||||||
std::string s1 = j1.dump();
|
std::string s1 = j1.dump();
|
||||||
@@ -350,13 +349,13 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", "bar"}};
|
json const j = { { "foo", "bar" } };
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3, 4};
|
json const j = { 1, 2, 3, 4 };
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,14 +401,14 @@ TEST_CASE("object inspection")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", "bar"}};
|
json const j = { { "foo", "bar" } };
|
||||||
json::value_t t = j;
|
json::value_t t = j;
|
||||||
CHECK(t == j.type());
|
CHECK(t == j.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3, 4};
|
json const j = { 1, 2, 3, 4 };
|
||||||
json::value_t t = j;
|
json::value_t t = j;
|
||||||
CHECK(t == j.type());
|
CHECK(t == j.type());
|
||||||
}
|
}
|
||||||
|
|||||||
+657
-661
File diff suppressed because it is too large
Load Diff
@@ -531,7 +531,7 @@ TEST_CASE("iterators 1")
|
|||||||
|
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3};
|
json j = { 1, 2, 3 };
|
||||||
json j_const(j);
|
json j_const(j);
|
||||||
|
|
||||||
SECTION("json + begin/end")
|
SECTION("json + begin/end")
|
||||||
@@ -715,7 +715,7 @@ TEST_CASE("iterators 1")
|
|||||||
|
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j = {{"A", 1}, {"B", 2}, {"C", 3}};
|
json j = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
|
||||||
json j_const(j);
|
json j_const(j);
|
||||||
|
|
||||||
SECTION("json + begin/end")
|
SECTION("json + begin/end")
|
||||||
@@ -1580,7 +1580,7 @@ TEST_CASE("iterators 1")
|
|||||||
}
|
}
|
||||||
SECTION("array")
|
SECTION("array")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3};
|
json j = { 1, 2, 3 };
|
||||||
json::const_iterator it = j.begin();
|
json::const_iterator it = j.begin();
|
||||||
CHECK(it == j.cbegin());
|
CHECK(it == j.cbegin());
|
||||||
it = j.begin();
|
it = j.begin();
|
||||||
@@ -1588,7 +1588,7 @@ TEST_CASE("iterators 1")
|
|||||||
}
|
}
|
||||||
SECTION("object")
|
SECTION("object")
|
||||||
{
|
{
|
||||||
json j = {{"A", 1}, {"B", 2}, {"C", 3}};
|
json j = { { "A", 1 }, { "B", 2 }, { "C", 3 } };
|
||||||
json::const_iterator it = j.begin();
|
json::const_iterator it = j.begin();
|
||||||
CHECK(it == j.cbegin());
|
CHECK(it == j.cbegin());
|
||||||
it = j.begin();
|
it = j.begin();
|
||||||
|
|||||||
+403
-199
@@ -27,7 +27,7 @@ TEST_CASE("iterators 2")
|
|||||||
{
|
{
|
||||||
SECTION("iterator comparisons")
|
SECTION("iterator comparisons")
|
||||||
{
|
{
|
||||||
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
|
json j_values = { nullptr, true, 42, 42u, 23.23, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3, 4, 5 }, "Hello, world" };
|
||||||
|
|
||||||
for (json& j : j_values)
|
for (json& j : j_values)
|
||||||
{
|
{
|
||||||
@@ -59,14 +59,14 @@ TEST_CASE("iterators 2")
|
|||||||
// comparison: not equal
|
// comparison: not equal
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 != it1) == !(it1 == it1) );
|
CHECK((it1 != it1) == !(it1 == it1));
|
||||||
CHECK( (it1 != it2) == !(it1 == it2) );
|
CHECK((it1 != it2) == !(it1 == it2));
|
||||||
CHECK( (it1 != it3) == !(it1 == it3) );
|
CHECK((it1 != it3) == !(it1 == it3));
|
||||||
CHECK( (it2 != it3) == !(it2 == it3) );
|
CHECK((it2 != it3) == !(it2 == it3));
|
||||||
CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
|
CHECK((it1_c != it1_c) == !(it1_c == it1_c));
|
||||||
CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
|
CHECK((it1_c != it2_c) == !(it1_c == it2_c));
|
||||||
CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
|
CHECK((it1_c != it3_c) == !(it1_c == it3_c));
|
||||||
CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
|
CHECK((it2_c != it3_c) == !(it2_c == it3_c));
|
||||||
}
|
}
|
||||||
|
|
||||||
// comparison: smaller
|
// comparison: smaller
|
||||||
@@ -74,23 +74,47 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 < it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 < it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c < it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c < it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -111,36 +135,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 <= it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 <= it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c <= it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c <= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 <= it1) == !(it1 < it1) );
|
CHECK((it1 <= it1) == !(it1 < it1));
|
||||||
CHECK( (it1 <= it2) == !(it2 < it1) );
|
CHECK((it1 <= it2) == !(it2 < it1));
|
||||||
CHECK( (it1 <= it3) == !(it3 < it1) );
|
CHECK((it1 <= it3) == !(it3 < it1));
|
||||||
CHECK( (it2 <= it3) == !(it3 < it2) );
|
CHECK((it2 <= it3) == !(it3 < it2));
|
||||||
CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
|
CHECK((it1_c <= it1_c) == !(it1_c < it1_c));
|
||||||
CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
|
CHECK((it1_c <= it2_c) == !(it2_c < it1_c));
|
||||||
CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
|
CHECK((it1_c <= it3_c) == !(it3_c < it1_c));
|
||||||
CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
|
CHECK((it2_c <= it3_c) == !(it3_c < it2_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,36 +197,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 > it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 > it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c > it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c > it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 > it1) == (it1 < it1) );
|
CHECK((it1 > it1) == (it1 < it1));
|
||||||
CHECK( (it1 > it2) == (it2 < it1) );
|
CHECK((it1 > it2) == (it2 < it1));
|
||||||
CHECK( (it1 > it3) == (it3 < it1) );
|
CHECK((it1 > it3) == (it3 < it1));
|
||||||
CHECK( (it2 > it3) == (it3 < it2) );
|
CHECK((it2 > it3) == (it3 < it2));
|
||||||
CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
|
CHECK((it1_c > it1_c) == (it1_c < it1_c));
|
||||||
CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
|
CHECK((it1_c > it2_c) == (it2_c < it1_c));
|
||||||
CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
|
CHECK((it1_c > it3_c) == (it3_c < it1_c));
|
||||||
CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
|
CHECK((it2_c > it3_c) == (it3_c < it2_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -187,36 +259,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 >= it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 >= it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c >= it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c >= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 >= it1) == !(it1 < it1) );
|
CHECK((it1 >= it1) == !(it1 < it1));
|
||||||
CHECK( (it1 >= it2) == !(it1 < it2) );
|
CHECK((it1 >= it2) == !(it1 < it2));
|
||||||
CHECK( (it1 >= it3) == !(it1 < it3) );
|
CHECK((it1 >= it3) == !(it1 < it3));
|
||||||
CHECK( (it2 >= it3) == !(it2 < it3) );
|
CHECK((it2 >= it3) == !(it2 < it3));
|
||||||
CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
|
CHECK((it1_c >= it1_c) == !(it1_c < it1_c));
|
||||||
CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
|
CHECK((it1_c >= it2_c) == !(it1_c < it2_c));
|
||||||
CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
|
CHECK((it1_c >= it3_c) == !(it1_c < it3_c));
|
||||||
CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
|
CHECK((it2_c >= it3_c) == !(it2_c < it3_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -231,10 +327,18 @@ TEST_CASE("iterators 2")
|
|||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
// the output differs in each loop, so we cannot fix a string for the expected exception
|
// the output differs in each loop, so we cannot fix a string for the expected exception
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.begin() == k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.begin() == k.begin(),
|
||||||
CHECK_THROWS_WITH_AS(j.cbegin() == k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
CHECK_THROWS_WITH_AS(j.begin() < k.begin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.cbegin() < k.cbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.cbegin() == k.cbegin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.begin() < k.begin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.cbegin() < k.cbegin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -243,8 +347,8 @@ TEST_CASE("iterators 2")
|
|||||||
|
|
||||||
SECTION("iterator arithmetic")
|
SECTION("iterator arithmetic")
|
||||||
{
|
{
|
||||||
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
|
json j_object = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
|
||||||
json j_array = {1, 2, 3, 4, 5, 6};
|
json j_array = { 1, 2, 3, 4, 5, 6 };
|
||||||
json j_null = nullptr;
|
json j_null = nullptr;
|
||||||
json j_value = 42;
|
json j_value = 42;
|
||||||
|
|
||||||
@@ -451,7 +555,7 @@ TEST_CASE("iterators 2")
|
|||||||
|
|
||||||
SECTION("reverse iterator comparisons")
|
SECTION("reverse iterator comparisons")
|
||||||
{
|
{
|
||||||
json j_values = {nullptr, true, 42, 42u, 23.23, {{"one", 1}, {"two", 2}}, {1, 2, 3, 4, 5}, "Hello, world"};
|
json j_values = { nullptr, true, 42, 42u, 23.23, { { "one", 1 }, { "two", 2 } }, { 1, 2, 3, 4, 5 }, "Hello, world" };
|
||||||
|
|
||||||
for (json& j : j_values)
|
for (json& j : j_values)
|
||||||
{
|
{
|
||||||
@@ -483,14 +587,14 @@ TEST_CASE("iterators 2")
|
|||||||
// comparison: not equal
|
// comparison: not equal
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 != it1) == !(it1 == it1) );
|
CHECK((it1 != it1) == !(it1 == it1));
|
||||||
CHECK( (it1 != it2) == !(it1 == it2) );
|
CHECK((it1 != it2) == !(it1 == it2));
|
||||||
CHECK( (it1 != it3) == !(it1 == it3) );
|
CHECK((it1 != it3) == !(it1 == it3));
|
||||||
CHECK( (it2 != it3) == !(it2 == it3) );
|
CHECK((it2 != it3) == !(it2 == it3));
|
||||||
CHECK( (it1_c != it1_c) == !(it1_c == it1_c) );
|
CHECK((it1_c != it1_c) == !(it1_c == it1_c));
|
||||||
CHECK( (it1_c != it2_c) == !(it1_c == it2_c) );
|
CHECK((it1_c != it2_c) == !(it1_c == it2_c));
|
||||||
CHECK( (it1_c != it3_c) == !(it1_c == it3_c) );
|
CHECK((it1_c != it3_c) == !(it1_c == it3_c));
|
||||||
CHECK( (it2_c != it3_c) == !(it2_c == it3_c) );
|
CHECK((it2_c != it3_c) == !(it2_c == it3_c));
|
||||||
}
|
}
|
||||||
|
|
||||||
// comparison: smaller
|
// comparison: smaller
|
||||||
@@ -498,23 +602,47 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 < it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 < it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 < it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c < it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c < it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c < it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c < it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -535,36 +663,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 <= it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 <= it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 <= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c <= it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c <= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c <= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c <= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 <= it1) == !(it1 < it1) );
|
CHECK((it1 <= it1) == !(it1 < it1));
|
||||||
CHECK( (it1 <= it2) == !(it2 < it1) );
|
CHECK((it1 <= it2) == !(it2 < it1));
|
||||||
CHECK( (it1 <= it3) == !(it3 < it1) );
|
CHECK((it1 <= it3) == !(it3 < it1));
|
||||||
CHECK( (it2 <= it3) == !(it3 < it2) );
|
CHECK((it2 <= it3) == !(it3 < it2));
|
||||||
CHECK( (it1_c <= it1_c) == !(it1_c < it1_c) );
|
CHECK((it1_c <= it1_c) == !(it1_c < it1_c));
|
||||||
CHECK( (it1_c <= it2_c) == !(it2_c < it1_c) );
|
CHECK((it1_c <= it2_c) == !(it2_c < it1_c));
|
||||||
CHECK( (it1_c <= it3_c) == !(it3_c < it1_c) );
|
CHECK((it1_c <= it3_c) == !(it3_c < it1_c));
|
||||||
CHECK( (it2_c <= it3_c) == !(it3_c < it2_c) );
|
CHECK((it2_c <= it3_c) == !(it3_c < it2_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,36 +725,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 > it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 > it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 > it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c > it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c > it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c > it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c > it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 > it1) == (it1 < it1) );
|
CHECK((it1 > it1) == (it1 < it1));
|
||||||
CHECK( (it1 > it2) == (it2 < it1) );
|
CHECK((it1 > it2) == (it2 < it1));
|
||||||
CHECK( (it1 > it3) == (it3 < it1) );
|
CHECK((it1 > it3) == (it3 < it1));
|
||||||
CHECK( (it2 > it3) == (it3 < it2) );
|
CHECK((it2 > it3) == (it3 < it2));
|
||||||
CHECK( (it1_c > it1_c) == (it1_c < it1_c) );
|
CHECK((it1_c > it1_c) == (it1_c < it1_c));
|
||||||
CHECK( (it1_c > it2_c) == (it2_c < it1_c) );
|
CHECK((it1_c > it2_c) == (it2_c < it1_c));
|
||||||
CHECK( (it1_c > it3_c) == (it3_c < it1_c) );
|
CHECK((it1_c > it3_c) == (it3_c < it1_c));
|
||||||
CHECK( (it2_c > it3_c) == (it3_c < it2_c) );
|
CHECK((it2_c > it3_c) == (it3_c < it2_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -611,36 +787,60 @@ TEST_CASE("iterators 2")
|
|||||||
if (j.type() == json::value_t::object)
|
if (j.type() == json::value_t::object)
|
||||||
{
|
{
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it1,
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it2,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 >= it3,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1 >= it3,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it1_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] (/5) cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it1, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it2, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it2 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1 >= it3, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it1_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c >= it1_c,
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it2_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
CHECK_THROWS_WITH_AS(it2_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(it1_c >= it3_c, "[json.exception.invalid_iterator.213] cannot compare order of object iterators", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(it1_c >= it2_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it2_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(it1_c >= it3_c,
|
||||||
|
"[json.exception.invalid_iterator.213] cannot compare order of object iterators",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check definition
|
// check definition
|
||||||
CHECK( (it1 >= it1) == !(it1 < it1) );
|
CHECK((it1 >= it1) == !(it1 < it1));
|
||||||
CHECK( (it1 >= it2) == !(it1 < it2) );
|
CHECK((it1 >= it2) == !(it1 < it2));
|
||||||
CHECK( (it1 >= it3) == !(it1 < it3) );
|
CHECK((it1 >= it3) == !(it1 < it3));
|
||||||
CHECK( (it2 >= it3) == !(it2 < it3) );
|
CHECK((it2 >= it3) == !(it2 < it3));
|
||||||
CHECK( (it1_c >= it1_c) == !(it1_c < it1_c) );
|
CHECK((it1_c >= it1_c) == !(it1_c < it1_c));
|
||||||
CHECK( (it1_c >= it2_c) == !(it1_c < it2_c) );
|
CHECK((it1_c >= it2_c) == !(it1_c < it2_c));
|
||||||
CHECK( (it1_c >= it3_c) == !(it1_c < it3_c) );
|
CHECK((it1_c >= it3_c) == !(it1_c < it3_c));
|
||||||
CHECK( (it2_c >= it3_c) == !(it2_c < it3_c) );
|
CHECK((it2_c >= it3_c) == !(it2_c < it3_c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -655,10 +855,18 @@ TEST_CASE("iterators 2")
|
|||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
// the output differs in each loop, so we cannot fix a string for the expected exception
|
// the output differs in each loop, so we cannot fix a string for the expected exception
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.rbegin() == k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.rbegin() == k.rbegin(),
|
||||||
CHECK_THROWS_WITH_AS(j.crbegin() == k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
CHECK_THROWS_WITH_AS(j.rbegin() < k.rbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
json::invalid_iterator&);
|
||||||
CHECK_THROWS_WITH_AS(j.crbegin() < k.crbegin(), "[json.exception.invalid_iterator.212] cannot compare iterators of different containers", json::invalid_iterator&);
|
CHECK_THROWS_WITH_AS(j.crbegin() == k.crbegin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.rbegin() < k.rbegin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
|
CHECK_THROWS_WITH_AS(j.crbegin() < k.crbegin(),
|
||||||
|
"[json.exception.invalid_iterator.212] cannot compare iterators of different containers",
|
||||||
|
json::invalid_iterator&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -667,8 +875,8 @@ TEST_CASE("iterators 2")
|
|||||||
|
|
||||||
SECTION("reverse iterator arithmetic")
|
SECTION("reverse iterator arithmetic")
|
||||||
{
|
{
|
||||||
json j_object = {{"one", 1}, {"two", 2}, {"three", 3}};
|
json j_object = { { "one", 1 }, { "two", 2 }, { "three", 3 } };
|
||||||
json j_array = {1, 2, 3, 4, 5, 6};
|
json j_array = { 1, 2, 3, 4, 5, 6 };
|
||||||
json j_null = nullptr;
|
json j_null = nullptr;
|
||||||
json j_value = 42;
|
json j_value = 42;
|
||||||
|
|
||||||
@@ -894,12 +1102,12 @@ TEST_CASE("iterators 2")
|
|||||||
}
|
}
|
||||||
|
|
||||||
// libstdc++ algorithms don't work with Clang 15 (04/2022)
|
// libstdc++ algorithms don't work with Clang 15 (04/2022)
|
||||||
#if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__))
|
#if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__))
|
||||||
SECTION("algorithms")
|
SECTION("algorithms")
|
||||||
{
|
{
|
||||||
SECTION("copy")
|
SECTION("copy")
|
||||||
{
|
{
|
||||||
json j{"foo", "bar"};
|
json j{ "foo", "bar" };
|
||||||
auto j_copied = json::array();
|
auto j_copied = json::array();
|
||||||
|
|
||||||
std::ranges::copy(j, std::back_inserter(j_copied));
|
std::ranges::copy(j, std::back_inserter(j_copied));
|
||||||
@@ -909,37 +1117,35 @@ TEST_CASE("iterators 2")
|
|||||||
|
|
||||||
SECTION("find_if")
|
SECTION("find_if")
|
||||||
{
|
{
|
||||||
json j{1, 3, 2, 4};
|
json j{ 1, 3, 2, 4 };
|
||||||
auto j_even = json::array();
|
auto j_even = json::array();
|
||||||
|
|
||||||
#if JSON_USE_IMPLICIT_CONVERSIONS
|
#if JSON_USE_IMPLICIT_CONVERSIONS
|
||||||
auto it = std::ranges::find_if(j, [](int v) noexcept
|
auto it = std::ranges::find_if(j, [](int v) noexcept {
|
||||||
{
|
|
||||||
return (v % 2) == 0;
|
return (v % 2) == 0;
|
||||||
});
|
});
|
||||||
#else
|
#else
|
||||||
auto it = std::ranges::find_if(j, [](const json & j) noexcept
|
auto it = std::ranges::find_if(j, [](const json& j) noexcept {
|
||||||
{
|
|
||||||
int v;
|
int v;
|
||||||
j.get_to(v);
|
j.get_to(v);
|
||||||
return (v % 2) == 0;
|
return (v % 2) == 0;
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
CHECK(*it == 2);
|
CHECK(*it == 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// libstdc++ views don't work with Clang 15 (04/2022)
|
// libstdc++ views don't work with Clang 15 (04/2022)
|
||||||
// libc++ hides limited ranges implementation behind guard macro
|
// libc++ hides limited ranges implementation behind guard macro
|
||||||
#if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
|
#if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
|
||||||
SECTION("views")
|
SECTION("views")
|
||||||
{
|
{
|
||||||
SECTION("reverse")
|
SECTION("reverse")
|
||||||
{
|
{
|
||||||
json j{1, 2, 3, 4, 5};
|
json j{ 1, 2, 3, 4, 5 };
|
||||||
json j_expected{5, 4, 3, 2, 1};
|
json j_expected{ 5, 4, 3, 2, 1 };
|
||||||
|
|
||||||
auto reversed = j | std::views::reverse;
|
auto reversed = j | std::views::reverse;
|
||||||
CHECK(std::ranges::equal(reversed, j_expected));
|
CHECK(std::ranges::equal(reversed, j_expected));
|
||||||
@@ -947,25 +1153,23 @@ TEST_CASE("iterators 2")
|
|||||||
|
|
||||||
SECTION("transform")
|
SECTION("transform")
|
||||||
{
|
{
|
||||||
json j
|
json j{
|
||||||
{
|
{ "a_key", "a_value" },
|
||||||
{ "a_key", "a_value"},
|
{ "b_key", "b_value" },
|
||||||
{ "b_key", "b_value"},
|
{ "c_key", "c_value" },
|
||||||
{ "c_key", "c_value"},
|
|
||||||
};
|
};
|
||||||
json j_expected{"a_key", "b_key", "c_key"};
|
json j_expected{ "a_key", "b_key", "c_key" };
|
||||||
|
|
||||||
auto transformed = j.items() | std::views::transform([](const auto & item)
|
auto transformed = j.items() | std::views::transform([](const auto& item) {
|
||||||
{
|
return item.key();
|
||||||
return item.key();
|
});
|
||||||
});
|
|
||||||
auto j_transformed = json::array();
|
auto j_transformed = json::array();
|
||||||
std::ranges::copy(transformed, std::back_inserter(j_transformed));
|
std::ranges::copy(transformed, std::back_inserter(j_transformed));
|
||||||
|
|
||||||
CHECK(j_transformed == j_expected);
|
CHECK(j_transformed == j_expected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
+199
-138
@@ -11,11 +11,11 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include "make_test_data_available.hpp"
|
#include "make_test_data_available.hpp"
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
TEST_CASE("JSON patch")
|
TEST_CASE("JSON patch")
|
||||||
{
|
{
|
||||||
@@ -77,9 +77,9 @@ TEST_CASE("JSON patch")
|
|||||||
{
|
{
|
||||||
// If removing an element from an array, any elements above the
|
// If removing an element from an array, any elements above the
|
||||||
// specified index are shifted one position to the left.
|
// specified index are shifted one position to the left.
|
||||||
json const doc = {1, 2, 3, 4};
|
json const doc = { 1, 2, 3, 4 };
|
||||||
json const patch = {{{"op", "remove"}, {"path", "/1"}}};
|
json const patch = { { { "op", "remove" }, { "path", "/1" } } };
|
||||||
CHECK(doc.patch(patch) == json({1, 3, 4}));
|
CHECK(doc.patch(patch) == json({ 1, 3, 4 }));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("A.1. Adding an Object Member")
|
SECTION("A.1. Adding an Object Member")
|
||||||
@@ -529,7 +529,7 @@ TEST_CASE("JSON patch")
|
|||||||
)"_json;
|
)"_json;
|
||||||
|
|
||||||
// The resulting JSON document:
|
// The resulting JSON document:
|
||||||
json expected = {1, 2, 3};
|
json expected = { 1, 2, 3 };
|
||||||
|
|
||||||
// check if patched value is as expected
|
// check if patched value is as expected
|
||||||
CHECK(doc.patch(patch) == expected);
|
CHECK(doc.patch(patch) == expected);
|
||||||
@@ -545,7 +545,7 @@ TEST_CASE("JSON patch")
|
|||||||
// exactly the number of elements in the array which is legal.
|
// exactly the number of elements in the array which is legal.
|
||||||
|
|
||||||
// An example target JSON document:
|
// An example target JSON document:
|
||||||
json const doc = {0, 1, 2};
|
json const doc = { 0, 1, 2 };
|
||||||
|
|
||||||
// A JSON Patch document:
|
// A JSON Patch document:
|
||||||
json const patch = R"(
|
json const patch = R"(
|
||||||
@@ -555,7 +555,7 @@ TEST_CASE("JSON patch")
|
|||||||
)"_json;
|
)"_json;
|
||||||
|
|
||||||
// The resulting JSON document:
|
// The resulting JSON document:
|
||||||
json expected = {0, 1, 2, 3};
|
json expected = { 0, 1, 2, 3 };
|
||||||
|
|
||||||
// check if patched value is as expected
|
// check if patched value is as expected
|
||||||
CHECK(doc.patch(patch) == expected);
|
CHECK(doc.patch(patch) == expected);
|
||||||
@@ -611,7 +611,7 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("replace")
|
SECTION("replace")
|
||||||
{
|
{
|
||||||
json const j = "string";
|
json const j = "string";
|
||||||
json const patch = {{{"op", "replace"}, {"path", ""}, {"value", 1}}};
|
json const patch = { { { "op", "replace" }, { "path", "" }, { "value", 1 } } };
|
||||||
CHECK(j.patch(patch) == json(1));
|
CHECK(j.patch(patch) == json(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -634,19 +634,19 @@ TEST_CASE("JSON patch")
|
|||||||
CHECK(target == R"({ "D": "Berlin", "F": "Paris", "GB": "London" })"_json);
|
CHECK(target == R"({ "D": "Berlin", "F": "Paris", "GB": "London" })"_json);
|
||||||
|
|
||||||
// create a diff from two JSONs
|
// create a diff from two JSONs
|
||||||
json p2 = json::diff(target, source); // NOLINT(readability-suspicious-call-argument)
|
json p2 = json::diff(target, source); // NOLINT(readability-suspicious-call-argument)
|
||||||
// p2 = [{"op": "delete", "path": "/GB"}]
|
// p2 = [{"op": "delete", "path": "/GB"}]
|
||||||
CHECK(p2 == R"([{"op":"remove","path":"/GB"}])"_json);
|
CHECK(p2 == R"([{"op":"remove","path":"/GB"}])"_json);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// a JSON value
|
// a JSON value
|
||||||
json j = {"good", "bad", "ugly"};
|
json j = { "good", "bad", "ugly" };
|
||||||
|
|
||||||
// a JSON pointer
|
// a JSON pointer
|
||||||
auto ptr = json::json_pointer("/2");
|
auto ptr = json::json_pointer("/2");
|
||||||
|
|
||||||
// use to access elements
|
// use to access elements
|
||||||
j[ptr] = {{"it", "cattivo"}};
|
j[ptr] = { { "it", "cattivo" } };
|
||||||
CHECK(j == R"(["good","bad",{"it":"cattivo"}])"_json);
|
CHECK(j == R"(["good","bad",{"it":"cattivo"}])"_json);
|
||||||
|
|
||||||
// use user-defined string literal
|
// use user-defined string literal
|
||||||
@@ -666,25 +666,31 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("not an array")
|
SECTION("not an array")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{"op", "add"}, {"path", ""}, {"value", 1}};
|
json const patch = { { "op", "add" }, { "path", "" }, { "value", 1 } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.104] parse error: JSON patch must be an array of objects",
|
||||||
|
json::parse_error&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("not an array of objects")
|
SECTION("not an array of objects")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {"op", "add", "path", "", "value", 1};
|
json const patch = { "op", "add", "path", "", "value", 1 };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.104] parse error: (/0) JSON patch must be an array of objects", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.104] parse error: (/0) JSON patch must be an array of objects",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.104] parse error: JSON patch must be an array of objects", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.104] parse error: JSON patch must be an array of objects",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'op'")
|
SECTION("missing 'op'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"foo", "bar"}}};
|
json const patch = { { { "foo", "bar" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation must have member 'op'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation must have member 'op'", json::parse_error&);
|
||||||
#else
|
#else
|
||||||
@@ -695,18 +701,22 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("non-string 'op'")
|
SECTION("non-string 'op'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", 1}}};
|
json const patch = { { { "op", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation must have string member 'op'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation must have string member 'op'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation must have string member 'op'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation must have string member 'op'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("invalid operation")
|
SECTION("invalid operation")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "foo"}, {"path", ""}}};
|
json const patch = { { { "op", "foo" }, { "path", "" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation value 'foo' is invalid", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation value 'foo' is invalid", json::parse_error&);
|
||||||
#else
|
#else
|
||||||
@@ -720,40 +730,52 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "add"}}};
|
json const patch = { { { "op", "add" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'add' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'add' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'add' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "add"}, {"path", 1}}};
|
json const patch = { { { "op", "add" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'add' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'add' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'add' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'value'")
|
SECTION("missing 'value'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "add"}, {"path", ""}}};
|
json const patch = { { { "op", "add" }, { "path", "" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'add' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'add' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'add' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'add' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("invalid array index")
|
SECTION("invalid array index")
|
||||||
{
|
{
|
||||||
json const j = {1, 2};
|
json const j = { 1, 2 };
|
||||||
json const patch = {{{"op", "add"}, {"path", "/4"}, {"value", 4}}};
|
json const patch = { { { "op", "add" }, { "path", "/4" }, { "value", 4 } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 4 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 4 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -763,43 +785,51 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "remove"}}};
|
json const patch = { { { "op", "remove" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'remove' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'remove' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'remove' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "remove"}, {"path", 1}}};
|
json const patch = { { { "op", "remove" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'remove' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'remove' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'remove' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'remove' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting target location (array)")
|
SECTION("nonexisting target location (array)")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3};
|
json const j = { 1, 2, 3 };
|
||||||
json const patch = {{{"op", "remove"}, {"path", "/17"}}};
|
json const patch = { { { "op", "remove" }, { "path", "/17" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting target location (object)")
|
SECTION("nonexisting target location (object)")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", 1}, {"bar", 2}};
|
json const j = { { "foo", 1 }, { "bar", 2 } };
|
||||||
json const patch = {{{"op", "remove"}, {"path", "/baz"}}};
|
json const patch = { { { "op", "remove" }, { "path", "/baz" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("root element as target location")
|
SECTION("root element as target location")
|
||||||
{
|
{
|
||||||
json const j = "string";
|
json const j = "string";
|
||||||
json const patch = {{{"op", "remove"}, {"path", ""}}};
|
json const patch = { { { "op", "remove" }, { "path", "" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -809,47 +839,59 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "replace"}}};
|
json const patch = { { { "op", "replace" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'replace' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "replace"}, {"path", 1}}};
|
json const patch = { { { "op", "replace" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'replace' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'value'")
|
SECTION("missing 'value'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "replace"}, {"path", ""}}};
|
json const patch = { { { "op", "replace" }, { "path", "" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'replace' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'replace' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'replace' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting target location (array)")
|
SECTION("nonexisting target location (array)")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3};
|
json const j = { 1, 2, 3 };
|
||||||
json const patch = {{{"op", "replace"}, {"path", "/17"}, {"value", 19}}};
|
json const patch = { { { "op", "replace" }, { "path", "/17" }, { "value", 19 } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 17 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting target location (object)")
|
SECTION("nonexisting target location (object)")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", 1}, {"bar", 2}};
|
json const j = { { "foo", 1 }, { "bar", 2 } };
|
||||||
json const patch = {{{"op", "replace"}, {"path", "/baz"}, {"value", 3}}};
|
json const patch = { { { "op", "replace" }, { "path", "/baz" }, { "value", 3 } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -859,60 +901,76 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "move"}}};
|
json const patch = { { { "op", "move" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'move' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'move' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'move' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "move"}, {"path", 1}}};
|
json const patch = { { { "op", "move" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'move' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'move' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'move' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'from'")
|
SECTION("missing 'from'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "move"}, {"path", ""}}};
|
json const patch = { { { "op", "move" }, { "path", "" } } };
|
||||||
CHECK_THROWS_AS(j.patch(patch), json::parse_error&);
|
CHECK_THROWS_AS(j.patch(patch), json::parse_error&);
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'move' must have member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'move' must have member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'move' must have member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'from'")
|
SECTION("non-string 'from'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "move"}, {"path", ""}, {"from", 1}}};
|
json const patch = { { { "op", "move" }, { "path", "" }, { "from", 1 } } };
|
||||||
CHECK_THROWS_AS(j.patch(patch), json::parse_error&);
|
CHECK_THROWS_AS(j.patch(patch), json::parse_error&);
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'move' must have string member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'move' must have string member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'move' must have string member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'move' must have string member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting from location (array)")
|
SECTION("nonexisting from location (array)")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3};
|
json const j = { 1, 2, 3 };
|
||||||
json const patch = {{{"op", "move"}, {"path", "/0"}, {"from", "/5"}}};
|
json const patch = { { { "op", "move" }, { "path", "/0" }, { "from", "/5" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting from location (object)")
|
SECTION("nonexisting from location (object)")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", 1}, {"bar", 2}};
|
json const j = { { "foo", 1 }, { "bar", 2 } };
|
||||||
json const patch = {{{"op", "move"}, {"path", "/baz"}, {"from", "/baz"}}};
|
json const patch = { { { "op", "move" }, { "path", "/baz" }, { "from", "/baz" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -922,58 +980,74 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "copy"}}};
|
json const patch = { { { "op", "copy" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'copy' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "copy"}, {"path", 1}}};
|
json const patch = { { { "op", "copy" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'from'")
|
SECTION("missing 'from'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "copy"}, {"path", ""}}};
|
json const patch = { { { "op", "copy" }, { "path", "" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'copy' must have member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'from'")
|
SECTION("non-string 'from'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "copy"}, {"path", ""}, {"from", 1}}};
|
json const patch = { { { "op", "copy" }, { "path", "" }, { "from", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have string member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'copy' must have string member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'from'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'copy' must have string member 'from'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting from location (array)")
|
SECTION("nonexisting from location (array)")
|
||||||
{
|
{
|
||||||
json const j = {1, 2, 3};
|
json const j = { 1, 2, 3 };
|
||||||
json const patch = {{{"op", "copy"}, {"path", "/0"}, {"from", "/5"}}};
|
json const patch = { { { "op", "copy" }, { "path", "/0" }, { "from", "/5" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("nonexisting from location (object)")
|
SECTION("nonexisting from location (object)")
|
||||||
{
|
{
|
||||||
json const j = {{"foo", 1}, {"bar", 2}};
|
json const j = { { "foo", 1 }, { "bar", 2 } };
|
||||||
json const patch = {{{"op", "copy"}, {"path", "/fob"}, {"from", "/baz"}}};
|
json const patch = { { { "op", "copy" }, { "path", "/fob" }, { "from", "/baz" } } };
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.out_of_range.403] key 'baz' not found", json::out_of_range&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -983,33 +1057,45 @@ TEST_CASE("JSON patch")
|
|||||||
SECTION("missing 'path'")
|
SECTION("missing 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "test"}}};
|
json const patch = { { { "op", "test" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'test' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'test' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'test' must have member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("non-string 'path'")
|
SECTION("non-string 'path'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "test"}, {"path", 1}}};
|
json const patch = { { { "op", "test" }, { "path", 1 } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'test' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'test' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have string member 'path'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'test' must have string member 'path'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("missing 'value'")
|
SECTION("missing 'value'")
|
||||||
{
|
{
|
||||||
json const j;
|
json const j;
|
||||||
json const patch = {{{"op", "test"}, {"path", ""}}};
|
json const patch = { { { "op", "test" }, { "path", "" } } };
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: (/0) operation 'test' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: (/0) operation 'test' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(j.patch(patch), "[json.exception.parse_error.105] parse error: operation 'test' must have member 'value'", json::parse_error&);
|
CHECK_THROWS_WITH_AS(j.patch(patch),
|
||||||
|
"[json.exception.parse_error.105] parse error: operation 'test' must have member 'value'",
|
||||||
|
json::parse_error&);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1216,77 +1302,52 @@ TEST_CASE("JSON patch")
|
|||||||
{
|
{
|
||||||
SECTION("add")
|
SECTION("add")
|
||||||
{
|
{
|
||||||
CHECK(R"( {} )"_json.patch(
|
CHECK(R"( {} )"_json.patch(R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json) == R"( {"foo": "bar"} )"_json);
|
||||||
R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json
|
|
||||||
) == R"( {"foo": "bar"} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [1, 3]} )"_json.patch(
|
CHECK(R"( {"foo": [1, 3]} )"_json.patch(R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json) == R"( {"foo": "bar"} )"_json);
|
||||||
R"( [{"op": "add", "path": "/foo", "value": "bar"}] )"_json
|
|
||||||
) == R"( {"foo": "bar"} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [{}]} )"_json.patch(
|
CHECK(R"( {"foo": [{}]} )"_json.patch(R"( [{"op": "add", "path": "/foo/0/bar", "value": "baz"}] )"_json) == R"( {"foo": [{"bar": "baz"}]} )"_json);
|
||||||
R"( [{"op": "add", "path": "/foo/0/bar", "value": "baz"}] )"_json
|
|
||||||
) == R"( {"foo": [{"bar": "baz"}]} )"_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("remove")
|
SECTION("remove")
|
||||||
{
|
{
|
||||||
CHECK(R"( {"foo": "bar"} )"_json.patch(
|
CHECK(R"( {"foo": "bar"} )"_json.patch(R"( [{"op": "remove", "path": "/foo"}] )"_json) == R"( {} )"_json);
|
||||||
R"( [{"op": "remove", "path": "/foo"}] )"_json
|
|
||||||
) == R"( {} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
|
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(R"( [{"op": "remove", "path": "/foo/1"}] )"_json) == R"( {"foo": [1, 3]} )"_json);
|
||||||
R"( [{"op": "remove", "path": "/foo/1"}] )"_json
|
|
||||||
) == R"( {"foo": [1, 3]} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(
|
CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(R"( [{"op": "remove", "path": "/foo/0/bar"}] )"_json) == R"( {"foo": [{}]} )"_json);
|
||||||
R"( [{"op": "remove", "path": "/foo/0/bar"}] )"_json
|
|
||||||
) == R"( {"foo": [{}]} )"_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("replace")
|
SECTION("replace")
|
||||||
{
|
{
|
||||||
CHECK(R"( {"foo": "bar"} )"_json.patch(
|
CHECK(R"( {"foo": "bar"} )"_json.patch(R"( [{"op": "replace", "path": "/foo", "value": 1}] )"_json) == R"( {"foo": 1} )"_json);
|
||||||
R"( [{"op": "replace", "path": "/foo", "value": 1}] )"_json
|
|
||||||
) == R"( {"foo": 1} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
|
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(R"( [{"op": "replace", "path": "/foo/1", "value": 4}] )"_json) == R"( {"foo": [1, 4, 3]} )"_json);
|
||||||
R"( [{"op": "replace", "path": "/foo/1", "value": 4}] )"_json
|
|
||||||
) == R"( {"foo": [1, 4, 3]} )"_json);
|
|
||||||
|
|
||||||
CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(
|
CHECK(R"( {"foo": [{"bar": "baz"}]} )"_json.patch(R"( [{"op": "replace", "path": "/foo/0/bar", "value": 1}] )"_json) ==
|
||||||
R"( [{"op": "replace", "path": "/foo/0/bar", "value": 1}] )"_json
|
R"( {"foo": [{"bar": 1}]} )"_json);
|
||||||
) == R"( {"foo": [{"bar": 1}]} )"_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("move")
|
SECTION("move")
|
||||||
{
|
{
|
||||||
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
|
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(R"( [{"op": "move", "from": "/foo", "path": "/bar"}] )"_json) == R"( {"bar": [1, 2, 3]} )"_json);
|
||||||
R"( [{"op": "move", "from": "/foo", "path": "/bar"}] )"_json
|
|
||||||
) == R"( {"bar": [1, 2, 3]} )"_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy")
|
SECTION("copy")
|
||||||
{
|
{
|
||||||
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(
|
CHECK(R"( {"foo": [1, 2, 3]} )"_json.patch(R"( [{"op": "copy", "from": "/foo/1", "path": "/bar"}] )"_json) ==
|
||||||
R"( [{"op": "copy", "from": "/foo/1", "path": "/bar"}] )"_json
|
R"( {"foo": [1, 2, 3], "bar": 2} )"_json);
|
||||||
) == R"( {"foo": [1, 2, 3], "bar": 2} )"_json);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("copy")
|
SECTION("copy")
|
||||||
{
|
{
|
||||||
CHECK_NOTHROW(R"( {"foo": "bar"} )"_json.patch(
|
CHECK_NOTHROW(R"( {"foo": "bar"} )"_json.patch(R"( [{"op": "test", "path": "/foo", "value": "bar"}] )"_json));
|
||||||
R"( [{"op": "test", "path": "/foo", "value": "bar"}] )"_json));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Tests from github.com/json-patch/json-patch-tests")
|
SECTION("Tests from github.com/json-patch/json-patch-tests")
|
||||||
{
|
{
|
||||||
for (const auto* filename :
|
for (const auto* filename : { TEST_DATA_DIRECTORY "/json-patch-tests/spec_tests.json", TEST_DATA_DIRECTORY "/json-patch-tests/tests.json" })
|
||||||
{
|
|
||||||
TEST_DATA_DIRECTORY "/json-patch-tests/spec_tests.json",
|
|
||||||
TEST_DATA_DIRECTORY "/json-patch-tests/tests.json"
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
CAPTURE(filename)
|
CAPTURE(filename)
|
||||||
std::ifstream f(filename);
|
std::ifstream f(filename);
|
||||||
|
|||||||
+127
-169
@@ -12,7 +12,7 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
@@ -23,26 +23,26 @@ TEST_CASE("JSON pointers")
|
|||||||
SECTION("errors")
|
SECTION("errors")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH_AS(json::json_pointer("foo"),
|
CHECK_THROWS_WITH_AS(json::json_pointer("foo"),
|
||||||
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'", json::parse_error&);
|
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(json::json_pointer("/~~"),
|
CHECK_THROWS_WITH_AS(json::json_pointer("/~~"),
|
||||||
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&);
|
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(json::json_pointer("/~"),
|
CHECK_THROWS_WITH_AS(json::json_pointer("/~"),
|
||||||
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&);
|
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
json::json_pointer p;
|
json::json_pointer p;
|
||||||
CHECK_THROWS_WITH_AS(p.top(),
|
CHECK_THROWS_WITH_AS(p.top(), "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(p.pop_back(), "[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(p.pop_back(),
|
|
||||||
"[json.exception.out_of_range.405] JSON pointer has no parent", json::out_of_range&);
|
|
||||||
|
|
||||||
SECTION("array index error")
|
SECTION("array index error")
|
||||||
{
|
{
|
||||||
json v = {1, 2, 3, 4};
|
json v = { 1, 2, 3, 4 };
|
||||||
json::json_pointer const ptr("/10e");
|
json::json_pointer const ptr("/10e");
|
||||||
CHECK_THROWS_WITH_AS(v[ptr],
|
CHECK_THROWS_WITH_AS(v[ptr], "[json.exception.out_of_range.404] unresolved reference token '10e'", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.404] unresolved reference token '10e'", json::out_of_range&);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,22 +131,22 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
CHECK(!j.contains(json::json_pointer("/a/c/1")));
|
CHECK(!j.contains(json::json_pointer("/a/c/1")));
|
||||||
CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
|
CHECK_NOTHROW(j[json::json_pointer("/a/c/1")] = 42);
|
||||||
CHECK(j["a"]["c"] == json({nullptr, 42}));
|
CHECK(j["a"]["c"] == json({ nullptr, 42 }));
|
||||||
CHECK(j.contains(json::json_pointer("/a/c/1")));
|
CHECK(j.contains(json::json_pointer("/a/c/1")));
|
||||||
|
|
||||||
CHECK(!j.contains(json::json_pointer("/a/d/-")));
|
CHECK(!j.contains(json::json_pointer("/a/d/-")));
|
||||||
CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
|
CHECK_NOTHROW(j[json::json_pointer("/a/d/-")] = 42);
|
||||||
CHECK(!j.contains(json::json_pointer("/a/d/-")));
|
CHECK(!j.contains(json::json_pointer("/a/d/-")));
|
||||||
CHECK(j["a"]["d"] == json::array({42}));
|
CHECK(j["a"]["d"] == json::array({ 42 }));
|
||||||
// "/a/b" works for JSON {"a": {"b": 42}}
|
// "/a/b" works for JSON {"a": {"b": 42}}
|
||||||
CHECK(json({{"a", {{"b", 42}}}})[json::json_pointer("/a/b")] == json(42));
|
CHECK(json({ { "a", { { "b", 42 } } } })[json::json_pointer("/a/b")] == json(42));
|
||||||
|
|
||||||
// unresolved access
|
// unresolved access
|
||||||
json j_primitive = 1;
|
json j_primitive = 1;
|
||||||
CHECK_THROWS_WITH_AS(j_primitive["/foo"_json_pointer],
|
CHECK_THROWS_WITH_AS(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
|
||||||
CHECK_THROWS_WITH_AS(j_primitive.at("/foo"_json_pointer),
|
CHECK_THROWS_WITH_AS(j_primitive.at("/foo"_json_pointer),
|
||||||
"[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
"[json.exception.out_of_range.404] unresolved reference token 'foo'",
|
||||||
|
json::out_of_range&);
|
||||||
CHECK(!j_primitive.contains(json::json_pointer("/foo")));
|
CHECK(!j_primitive.contains(json::json_pointer("/foo")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,15 +205,14 @@ TEST_CASE("JSON pointers")
|
|||||||
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
CHECK(j[json::json_pointer("/m~0n")] == j["m~n"]);
|
||||||
|
|
||||||
// unescaped access
|
// unescaped access
|
||||||
CHECK_THROWS_WITH_AS(j.at(json::json_pointer("/a/b")),
|
CHECK_THROWS_WITH_AS(j.at(json::json_pointer("/a/b")), "[json.exception.out_of_range.403] key 'a' not found", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.403] key 'a' not found", json::out_of_range&);
|
|
||||||
|
|
||||||
// unresolved access
|
// unresolved access
|
||||||
const json j_primitive = 1;
|
const json j_primitive = 1;
|
||||||
CHECK_THROWS_WITH_AS(j_primitive["/foo"_json_pointer],
|
CHECK_THROWS_WITH_AS(j_primitive["/foo"_json_pointer], "[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
|
||||||
CHECK_THROWS_WITH_AS(j_primitive.at("/foo"_json_pointer),
|
CHECK_THROWS_WITH_AS(j_primitive.at("/foo"_json_pointer),
|
||||||
"[json.exception.out_of_range.404] unresolved reference token 'foo'", json::out_of_range&);
|
"[json.exception.out_of_range.404] unresolved reference token 'foo'",
|
||||||
|
json::out_of_range&);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("user-defined string literal")
|
SECTION("user-defined string literal")
|
||||||
@@ -252,7 +251,7 @@ TEST_CASE("JSON pointers")
|
|||||||
{
|
{
|
||||||
SECTION("nonconst access")
|
SECTION("nonconst access")
|
||||||
{
|
{
|
||||||
json j = {1, 2, 3};
|
json j = { 1, 2, 3 };
|
||||||
const json j_const = j;
|
const json j_const = j;
|
||||||
|
|
||||||
// check reading access
|
// check reading access
|
||||||
@@ -270,17 +269,21 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
// assign to nonexisting index (with gap)
|
// assign to nonexisting index (with gap)
|
||||||
j["/5"_json_pointer] = 55;
|
j["/5"_json_pointer] = 55;
|
||||||
CHECK(j == json({1, 13, 3, 33, nullptr, 55}));
|
CHECK(j == json({ 1, 13, 3, 33, nullptr, 55 }));
|
||||||
|
|
||||||
// error with leading 0
|
// error with leading 0
|
||||||
CHECK_THROWS_WITH_AS(j["/01"_json_pointer],
|
CHECK_THROWS_WITH_AS(j["/01"_json_pointer],
|
||||||
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const["/01"_json_pointer],
|
CHECK_THROWS_WITH_AS(j_const["/01"_json_pointer],
|
||||||
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j.at("/01"_json_pointer),
|
CHECK_THROWS_WITH_AS(j.at("/01"_json_pointer),
|
||||||
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const.at("/01"_json_pointer),
|
CHECK_THROWS_WITH_AS(j_const.at("/01"_json_pointer),
|
||||||
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'", json::parse_error&);
|
"[json.exception.parse_error.106] parse error: array index '01' must not begin with '0'",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK(!j.contains("/01"_json_pointer));
|
CHECK(!j.contains("/01"_json_pointer));
|
||||||
CHECK(!j.contains("/01"_json_pointer));
|
CHECK(!j.contains("/01"_json_pointer));
|
||||||
@@ -289,24 +292,28 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
// error with incorrect numbers
|
// error with incorrect numbers
|
||||||
CHECK_THROWS_WITH_AS(j["/one"_json_pointer] = 1,
|
CHECK_THROWS_WITH_AS(j["/one"_json_pointer] = 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const["/one"_json_pointer] == 1,
|
CHECK_THROWS_WITH_AS(j_const["/one"_json_pointer] == 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j.at("/one"_json_pointer) = 1,
|
CHECK_THROWS_WITH_AS(j.at("/one"_json_pointer) = 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const.at("/one"_json_pointer) == 1,
|
CHECK_THROWS_WITH_AS(j_const.at("/one"_json_pointer) == 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j["/+1"_json_pointer] = 1,
|
CHECK_THROWS_WITH_AS(j["/+1"_json_pointer] = 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index '+1' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index '+1' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const["/+1"_json_pointer] == 1,
|
CHECK_THROWS_WITH_AS(j_const["/+1"_json_pointer] == 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index '+1' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index '+1' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j["/1+1"_json_pointer] = 1,
|
CHECK_THROWS_WITH_AS(j["/1+1"_json_pointer] = 1, "[json.exception.out_of_range.404] unresolved reference token '1+1'", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.404] unresolved reference token '1+1'", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j_const["/1+1"_json_pointer] == 1, "[json.exception.out_of_range.404] unresolved reference token '1+1'", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j_const["/1+1"_json_pointer] == 1,
|
|
||||||
"[json.exception.out_of_range.404] unresolved reference token '1+1'", json::out_of_range&);
|
|
||||||
|
|
||||||
{
|
{
|
||||||
auto too_large_index = std::to_string((std::numeric_limits<unsigned long long>::max)()) + "1";
|
auto too_large_index = std::to_string((std::numeric_limits<unsigned long long>::max)()) + "1";
|
||||||
@@ -335,38 +342,38 @@ TEST_CASE("JSON pointers")
|
|||||||
DOCTEST_MSVC_SUPPRESS_WARNING_POP
|
DOCTEST_MSVC_SUPPRESS_WARNING_POP
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(j.at("/one"_json_pointer) = 1,
|
CHECK_THROWS_WITH_AS(j.at("/one"_json_pointer) = 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(j_const.at("/one"_json_pointer) == 1,
|
CHECK_THROWS_WITH_AS(j_const.at("/one"_json_pointer) == 1,
|
||||||
"[json.exception.parse_error.109] parse error: array index 'one' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'one' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
CHECK(!j.contains("/one"_json_pointer));
|
CHECK(!j.contains("/one"_json_pointer));
|
||||||
CHECK(!j.contains("/one"_json_pointer));
|
CHECK(!j.contains("/one"_json_pointer));
|
||||||
CHECK(!j_const.contains("/one"_json_pointer));
|
CHECK(!j_const.contains("/one"_json_pointer));
|
||||||
CHECK(!j_const.contains("/one"_json_pointer));
|
CHECK(!j_const.contains("/one"_json_pointer));
|
||||||
|
|
||||||
CHECK_THROWS_WITH_AS(json({{"/list/0", 1}, {"/list/1", 2}, {"/list/three", 3}}).unflatten(),
|
CHECK_THROWS_WITH_AS(json({ { "/list/0", 1 }, { "/list/1", 2 }, { "/list/three", 3 } }).unflatten(),
|
||||||
"[json.exception.parse_error.109] parse error: array index 'three' is not a number", json::parse_error&);
|
"[json.exception.parse_error.109] parse error: array index 'three' is not a number",
|
||||||
|
json::parse_error&);
|
||||||
|
|
||||||
// assign to "-"
|
// assign to "-"
|
||||||
j["/-"_json_pointer] = 99;
|
j["/-"_json_pointer] = 99;
|
||||||
CHECK(j == json({1, 13, 3, 33, nullptr, 55, 99}));
|
CHECK(j == json({ 1, 13, 3, 33, nullptr, 55, 99 }));
|
||||||
|
|
||||||
// error when using "-" in const object
|
// error when using "-" in const object
|
||||||
CHECK_THROWS_WITH_AS(j_const["/-"_json_pointer],
|
CHECK_THROWS_WITH_AS(j_const["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
|
||||||
CHECK(!j_const.contains("/-"_json_pointer));
|
CHECK(!j_const.contains("/-"_json_pointer));
|
||||||
|
|
||||||
// error when using "-" with at
|
// error when using "-" with at
|
||||||
CHECK_THROWS_WITH_AS(j.at("/-"_json_pointer),
|
CHECK_THROWS_WITH_AS(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (7) is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.402] array index '-' (7) is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j_const.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j_const.at("/-"_json_pointer),
|
|
||||||
"[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
|
||||||
CHECK(!j_const.contains("/-"_json_pointer));
|
CHECK(!j_const.contains("/-"_json_pointer));
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("const access")
|
SECTION("const access")
|
||||||
{
|
{
|
||||||
const json j = {1, 2, 3};
|
const json j = { 1, 2, 3 };
|
||||||
|
|
||||||
// check reading access
|
// check reading access
|
||||||
CHECK(j["/0"_json_pointer] == j[0]);
|
CHECK(j["/0"_json_pointer] == j[0]);
|
||||||
@@ -374,67 +381,45 @@ TEST_CASE("JSON pointers")
|
|||||||
CHECK(j["/2"_json_pointer] == j[2]);
|
CHECK(j["/2"_json_pointer] == j[2]);
|
||||||
|
|
||||||
// assign to nonexisting index
|
// assign to nonexisting index
|
||||||
CHECK_THROWS_WITH_AS(j.at("/3"_json_pointer),
|
CHECK_THROWS_WITH_AS(j.at("/3"_json_pointer), "[json.exception.out_of_range.401] array index 3 is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.401] array index 3 is out of range", json::out_of_range&);
|
|
||||||
CHECK(!j.contains("/3"_json_pointer));
|
CHECK(!j.contains("/3"_json_pointer));
|
||||||
|
|
||||||
// assign to nonexisting index (with gap)
|
// assign to nonexisting index (with gap)
|
||||||
CHECK_THROWS_WITH_AS(j.at("/5"_json_pointer),
|
CHECK_THROWS_WITH_AS(j.at("/5"_json_pointer), "[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.401] array index 5 is out of range", json::out_of_range&);
|
|
||||||
CHECK(!j.contains("/5"_json_pointer));
|
CHECK(!j.contains("/5"_json_pointer));
|
||||||
|
|
||||||
// assign to "-"
|
// assign to "-"
|
||||||
CHECK_THROWS_WITH_AS(j["/-"_json_pointer],
|
CHECK_THROWS_WITH_AS(j["/-"_json_pointer], "[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
||||||
"[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
CHECK_THROWS_WITH_AS(j.at("/-"_json_pointer), "[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
||||||
CHECK_THROWS_WITH_AS(j.at("/-"_json_pointer),
|
|
||||||
"[json.exception.out_of_range.402] array index '-' (3) is out of range", json::out_of_range&);
|
|
||||||
CHECK(!j.contains("/-"_json_pointer));
|
CHECK(!j.contains("/-"_json_pointer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("flatten")
|
SECTION("flatten")
|
||||||
{
|
{
|
||||||
json j =
|
json j = { { "pi", 3.141 },
|
||||||
{
|
{ "happy", true },
|
||||||
{"pi", 3.141},
|
{ "name", "Niels" },
|
||||||
{"happy", true},
|
{ "nothing", nullptr },
|
||||||
{"name", "Niels"},
|
{ "answer", { { "everything", 42 } } },
|
||||||
{"nothing", nullptr},
|
{ "list", { 1, 0, 2 } },
|
||||||
{
|
{ "object",
|
||||||
"answer", {
|
{ { "currency", "USD" }, { "value", 42.99 }, { "", "empty string" }, { "/", "slash" }, { "~", "tilde" }, { "~1", "tilde1" } } } };
|
||||||
{"everything", 42}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{"list", {1, 0, 2}},
|
|
||||||
{
|
|
||||||
"object", {
|
|
||||||
{"currency", "USD"},
|
|
||||||
{"value", 42.99},
|
|
||||||
{"", "empty string"},
|
|
||||||
{"/", "slash"},
|
|
||||||
{"~", "tilde"},
|
|
||||||
{"~1", "tilde1"}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
json j_flatten =
|
json j_flatten = { { "/pi", 3.141 },
|
||||||
{
|
{ "/happy", true },
|
||||||
{"/pi", 3.141},
|
{ "/name", "Niels" },
|
||||||
{"/happy", true},
|
{ "/nothing", nullptr },
|
||||||
{"/name", "Niels"},
|
{ "/answer/everything", 42 },
|
||||||
{"/nothing", nullptr},
|
{ "/list/0", 1 },
|
||||||
{"/answer/everything", 42},
|
{ "/list/1", 0 },
|
||||||
{"/list/0", 1},
|
{ "/list/2", 2 },
|
||||||
{"/list/1", 0},
|
{ "/object/currency", "USD" },
|
||||||
{"/list/2", 2},
|
{ "/object/value", 42.99 },
|
||||||
{"/object/currency", "USD"},
|
{ "/object/", "empty string" },
|
||||||
{"/object/value", 42.99},
|
{ "/object/~1", "slash" },
|
||||||
{"/object/", "empty string"},
|
{ "/object/~0", "tilde" },
|
||||||
{"/object/~1", "slash"},
|
{ "/object/~01", "tilde1" } };
|
||||||
{"/object/~0", "tilde"},
|
|
||||||
{"/object/~01", "tilde1"}
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if flattened result is as expected
|
// check if flattened result is as expected
|
||||||
CHECK(j.flatten() == j_flatten);
|
CHECK(j.flatten() == j_flatten);
|
||||||
@@ -443,20 +428,22 @@ TEST_CASE("JSON pointers")
|
|||||||
CHECK(j_flatten.unflatten() == j);
|
CHECK(j_flatten.unflatten() == j);
|
||||||
|
|
||||||
// error for nonobjects
|
// error for nonobjects
|
||||||
CHECK_THROWS_WITH_AS(json(1).unflatten(),
|
CHECK_THROWS_WITH_AS(json(1).unflatten(), "[json.exception.type_error.314] only objects can be unflattened", json::type_error&);
|
||||||
"[json.exception.type_error.314] only objects can be unflattened", json::type_error&);
|
|
||||||
|
|
||||||
// error for nonprimitve values
|
// error for nonprimitve values
|
||||||
#if JSON_DIAGNOSTICS
|
#if JSON_DIAGNOSTICS
|
||||||
CHECK_THROWS_WITH_AS(json({{"/1", {1, 2, 3}}}).unflatten(), "[json.exception.type_error.315] (/~11) values in object must be primitive", json::type_error&);
|
CHECK_THROWS_WITH_AS(json({ { "/1", { 1, 2, 3 } } }).unflatten(),
|
||||||
|
"[json.exception.type_error.315] (/~11) values in object must be primitive",
|
||||||
|
json::type_error&);
|
||||||
#else
|
#else
|
||||||
CHECK_THROWS_WITH_AS(json({{"/1", {1, 2, 3}}}).unflatten(), "[json.exception.type_error.315] values in object must be primitive", json::type_error&);
|
CHECK_THROWS_WITH_AS(json({ { "/1", { 1, 2, 3 } } }).unflatten(),
|
||||||
|
"[json.exception.type_error.315] values in object must be primitive",
|
||||||
|
json::type_error&);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// error for conflicting values
|
// error for conflicting values
|
||||||
json const j_error = {{"", 42}, {"/foo", 17}};
|
json const j_error = { { "", 42 }, { "/foo", 17 } };
|
||||||
CHECK_THROWS_WITH_AS(j_error.unflatten(),
|
CHECK_THROWS_WITH_AS(j_error.unflatten(), "[json.exception.type_error.313] invalid value to unflatten", json::type_error&);
|
||||||
"[json.exception.type_error.313] invalid value to unflatten", json::type_error&);
|
|
||||||
|
|
||||||
// explicit roundtrip check
|
// explicit roundtrip check
|
||||||
CHECK(j.flatten().unflatten() == j);
|
CHECK(j.flatten().unflatten() == j);
|
||||||
@@ -480,9 +467,7 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
SECTION("string representation")
|
SECTION("string representation")
|
||||||
{
|
{
|
||||||
for (const auto* ptr_str :
|
for (const auto* ptr_str : { "", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n" })
|
||||||
{"", "/foo", "/foo/0", "/", "/a~1b", "/c%d", "/e^f", "/g|h", "/i\\j", "/k\"l", "/ ", "/m~0n"
|
|
||||||
})
|
|
||||||
{
|
{
|
||||||
json::json_pointer const ptr(ptr_str);
|
json::json_pointer const ptr(ptr_str);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
@@ -514,30 +499,15 @@ TEST_CASE("JSON pointers")
|
|||||||
|
|
||||||
SECTION("empty, push, pop and parent")
|
SECTION("empty, push, pop and parent")
|
||||||
{
|
{
|
||||||
const json j =
|
const json j = { { "", "Hello" },
|
||||||
{
|
{ "pi", 3.141 },
|
||||||
{"", "Hello"},
|
{ "happy", true },
|
||||||
{"pi", 3.141},
|
{ "name", "Niels" },
|
||||||
{"happy", true},
|
{ "nothing", nullptr },
|
||||||
{"name", "Niels"},
|
{ "answer", { { "everything", 42 } } },
|
||||||
{"nothing", nullptr},
|
{ "list", { 1, 0, 2 } },
|
||||||
{
|
{ "object",
|
||||||
"answer", {
|
{ { "currency", "USD" }, { "value", 42.99 }, { "", "empty string" }, { "/", "slash" }, { "~", "tilde" }, { "~1", "tilde1" } } } };
|
||||||
{"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
|
// empty json_pointer returns the root JSON-object
|
||||||
auto ptr = ""_json_pointer;
|
auto ptr = ""_json_pointer;
|
||||||
@@ -584,36 +554,20 @@ TEST_CASE("JSON pointers")
|
|||||||
CHECK(ptr.empty());
|
CHECK(ptr.empty());
|
||||||
CHECK(j[ptr] == j);
|
CHECK(j[ptr] == j);
|
||||||
|
|
||||||
CHECK_THROWS_WITH(ptr.pop_back(),
|
CHECK_THROWS_WITH(ptr.pop_back(), "[json.exception.out_of_range.405] JSON pointer has no parent");
|
||||||
"[json.exception.out_of_range.405] JSON pointer has no parent");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("operators")
|
SECTION("operators")
|
||||||
{
|
{
|
||||||
const json j =
|
const json j = { { "", "Hello" },
|
||||||
{
|
{ "pi", 3.141 },
|
||||||
{"", "Hello"},
|
{ "happy", true },
|
||||||
{"pi", 3.141},
|
{ "name", "Niels" },
|
||||||
{"happy", true},
|
{ "nothing", nullptr },
|
||||||
{"name", "Niels"},
|
{ "answer", { { "everything", 42 } } },
|
||||||
{"nothing", nullptr},
|
{ "list", { 1, 0, 2 } },
|
||||||
{
|
{ "object",
|
||||||
"answer", {
|
{ { "currency", "USD" }, { "value", 42.99 }, { "", "empty string" }, { "/", "slash" }, { "~", "tilde" }, { "~1", "tilde1" } } } };
|
||||||
{"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
|
// empty json_pointer returns the root JSON-object
|
||||||
auto ptr = ""_json_pointer;
|
auto ptr = ""_json_pointer;
|
||||||
@@ -652,8 +606,8 @@ TEST_CASE("JSON pointers")
|
|||||||
SECTION("equality comparison")
|
SECTION("equality comparison")
|
||||||
{
|
{
|
||||||
const char* ptr_cpstring = "/foo/bar";
|
const char* ptr_cpstring = "/foo/bar";
|
||||||
const char ptr_castring[] = "/foo/bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
const char ptr_castring[] = "/foo/bar"; // NOLINT(hicpp-avoid-c-arrays,modernize-avoid-c-arrays,cppcoreguidelines-avoid-c-arrays)
|
||||||
std::string ptr_string{"/foo/bar"};
|
std::string ptr_string{ "/foo/bar" };
|
||||||
auto ptr1 = json::json_pointer(ptr_string);
|
auto ptr1 = json::json_pointer(ptr_string);
|
||||||
auto ptr2 = json::json_pointer(ptr_string);
|
auto ptr2 = json::json_pointer(ptr_string);
|
||||||
|
|
||||||
@@ -687,13 +641,17 @@ TEST_CASE("JSON pointers")
|
|||||||
SECTION("exceptions")
|
SECTION("exceptions")
|
||||||
{
|
{
|
||||||
CHECK_THROWS_WITH_AS(ptr1 == "foo",
|
CHECK_THROWS_WITH_AS(ptr1 == "foo",
|
||||||
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'", json::parse_error&);
|
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS("foo" == ptr1,
|
CHECK_THROWS_WITH_AS("foo" == ptr1,
|
||||||
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'", json::parse_error&);
|
"[json.exception.parse_error.107] parse error at byte 1: JSON pointer must be empty or begin with '/' - was: 'foo'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS(ptr1 == "/~~",
|
CHECK_THROWS_WITH_AS(ptr1 == "/~~",
|
||||||
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&);
|
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'",
|
||||||
|
json::parse_error&);
|
||||||
CHECK_THROWS_WITH_AS("/~~" == ptr1,
|
CHECK_THROWS_WITH_AS("/~~" == ptr1,
|
||||||
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'", json::parse_error&);
|
"[json.exception.parse_error.108] parse error: escape character '~' must be followed with '0' or '1'",
|
||||||
|
json::parse_error&);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -708,7 +666,7 @@ TEST_CASE("JSON pointers")
|
|||||||
// build with C++20
|
// build with C++20
|
||||||
// JSON_HAS_CPP_20
|
// JSON_HAS_CPP_20
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
CHECK((ptr1 <=> ptr2) == std::strong_ordering::less); // *NOPAD*
|
CHECK((ptr1 <=> ptr2) == std::strong_ordering::less); // *NOPAD*
|
||||||
CHECK(ptr2 > ptr1);
|
CHECK(ptr2 > ptr1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -741,10 +699,10 @@ TEST_CASE("JSON pointers")
|
|||||||
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_j::string_t>::value);
|
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_j::string_t>::value);
|
||||||
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_oj::string_t>::value);
|
CHECK(std::is_same<json_ptr_str::string_t, json_ptr_oj::string_t>::value);
|
||||||
|
|
||||||
std::string const ptr_string{"/foo/0"};
|
std::string const ptr_string{ "/foo/0" };
|
||||||
json_ptr_str ptr{ptr_string};
|
json_ptr_str ptr{ ptr_string };
|
||||||
json_ptr_j ptr_j{ptr_string};
|
json_ptr_j ptr_j{ ptr_string };
|
||||||
json_ptr_oj ptr_oj{ptr_string};
|
json_ptr_oj ptr_oj{ ptr_string };
|
||||||
|
|
||||||
CHECK(j.contains(ptr));
|
CHECK(j.contains(ptr));
|
||||||
CHECK(j.contains(ptr_j));
|
CHECK(j.contains(ptr_j));
|
||||||
|
|||||||
@@ -26,4 +26,3 @@ TEST_CASE("tests on very large JSONs")
|
|||||||
CHECK_NOTHROW(_ = nlohmann::json::parse(s));
|
CHECK_NOTHROW(_ = nlohmann::json::parse(s));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TEST_CASE("JSON Merge Patch")
|
TEST_CASE("JSON Merge Patch")
|
||||||
|
|||||||
@@ -20,13 +20,7 @@ TEST_CASE("version information")
|
|||||||
CHECK(j["name"] == "JSON for Modern C++");
|
CHECK(j["name"] == "JSON for Modern C++");
|
||||||
CHECK(j["copyright"] == "(C) 2013-2023 Niels Lohmann");
|
CHECK(j["copyright"] == "(C) 2013-2023 Niels Lohmann");
|
||||||
CHECK(j["url"] == "https://github.com/nlohmann/json");
|
CHECK(j["url"] == "https://github.com/nlohmann/json");
|
||||||
CHECK(j["version"] == json(
|
CHECK(j["version"] == json({ { "string", "3.11.3" }, { "major", 3 }, { "minor", 11 }, { "patch", 3 } }));
|
||||||
{
|
|
||||||
{"string", "3.11.3"},
|
|
||||||
{"major", 3},
|
|
||||||
{"minor", 11},
|
|
||||||
{"patch", 3}
|
|
||||||
}));
|
|
||||||
|
|
||||||
CHECK(j.find("platform") != j.end());
|
CHECK(j.find("platform") != j.end());
|
||||||
CHECK(j.at("compiler").find("family") != j.at("compiler").end());
|
CHECK(j.at("compiler").find("family") != j.at("compiler").end());
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user