mirror of
https://github.com/nlohmann/json.git
synced 2026-09-29 11:10:30 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ab47ef138 | ||
|
|
afba254d39 | ||
|
|
1419aeff60 | ||
|
|
e0ee07fe73 | ||
|
|
dc4a70e7b4 |
@@ -67,6 +67,7 @@ jobs:
|
|||||||
|
|
||||||
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json.json -s .
|
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 .
|
python3 $TOOL_DIR/amalgamate.py -c $TOOL_DIR/config_json_fwd.json -s .
|
||||||
|
cp include/nlohmann/json_literals.hpp $INCLUDE_DIR/json_literals.hpp
|
||||||
|
|
||||||
# the header list of the Bazel "json" target must match the files in include/
|
# the header list of the Bazel "json" target must match the files in include/
|
||||||
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
cmake -P cmake/scripts/gen_bazel_build_file.cmake
|
||||||
|
|||||||
@@ -65,6 +65,7 @@ cc_library(
|
|||||||
"include/nlohmann/detail/value_t.hpp",
|
"include/nlohmann/detail/value_t.hpp",
|
||||||
"include/nlohmann/json.hpp",
|
"include/nlohmann/json.hpp",
|
||||||
"include/nlohmann/json_fwd.hpp",
|
"include/nlohmann/json_fwd.hpp",
|
||||||
|
"include/nlohmann/json_literals.hpp",
|
||||||
"include/nlohmann/ordered_map.hpp",
|
"include/nlohmann/ordered_map.hpp",
|
||||||
"include/nlohmann/thirdparty/hedley/hedley.hpp",
|
"include/nlohmann/thirdparty/hedley/hedley.hpp",
|
||||||
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
|
"include/nlohmann/thirdparty/hedley/hedley_undef.hpp",
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ TESTS_SRCS=$(shell find tests -type f \( -name '*.hpp' -o -name '*.cpp' -o -name
|
|||||||
# the single headers (amalgamated from the source files)
|
# the single headers (amalgamated from the source files)
|
||||||
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
|
AMALGAMATED_FILE=single_include/nlohmann/json.hpp
|
||||||
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
||||||
|
# json_literals.hpp only includes <nlohmann/json.hpp>, so it is copied verbatim
|
||||||
|
AMALGAMATED_LITERALS_FILE=single_include/nlohmann/json_literals.hpp
|
||||||
|
|
||||||
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -29,7 +31,7 @@ AMALGAMATED_FWD_FILE=single_include/nlohmann/json_fwd.hpp
|
|||||||
|
|
||||||
# main target
|
# main target
|
||||||
all:
|
all:
|
||||||
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd}.hpp from the include/nlohmann sources"
|
@echo "amalgamate - amalgamate files single_include/nlohmann/json{,_fwd,_literals}.hpp from the include/nlohmann sources"
|
||||||
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
@echo "BUILD.bazel - regenerate the Bazel BUILD file from the include/nlohmann sources"
|
||||||
@echo "ChangeLog.md - generate ChangeLog file"
|
@echo "ChangeLog.md - generate ChangeLog file"
|
||||||
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
|
@echo "check-amalgamation - check whether sources have been amalgamated and BUILD.bazel is up to date"
|
||||||
@@ -154,14 +156,14 @@ install_astyle:
|
|||||||
|
|
||||||
# call the Artistic Style pretty printer on all source files
|
# call the Artistic Style pretty printer on all source files
|
||||||
pretty: install_astyle
|
pretty: install_astyle
|
||||||
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) docs/mkdocs/docs/examples/*.cpp
|
$(ASTYLE) --project=tools/astyle/.astylerc $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) docs/mkdocs/docs/examples/*.cpp
|
||||||
|
|
||||||
# call the Clang-Format on all source files
|
# call the Clang-Format on all source files
|
||||||
pretty_format:
|
pretty_format:
|
||||||
for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/mkdocs/docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
|
for FILE in $(SRCS) $(TESTS_SRCS) $(AMALGAMATED_FILE) docs/mkdocs/docs/examples/*.cpp; do echo $$FILE; clang-format -i $$FILE; done
|
||||||
|
|
||||||
# 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) $(AMALGAMATED_LITERALS_FILE)
|
||||||
$(MAKE) pretty
|
$(MAKE) pretty
|
||||||
|
|
||||||
# call the amalgamation tool for json.hpp
|
# call the amalgamation tool for json.hpp
|
||||||
@@ -172,16 +174,23 @@ $(AMALGAMATED_FILE): $(SRCS)
|
|||||||
$(AMALGAMATED_FWD_FILE): $(SRCS)
|
$(AMALGAMATED_FWD_FILE): $(SRCS)
|
||||||
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_fwd.json -s . --verbose=yes
|
tools/amalgamate/amalgamate.py -c tools/amalgamate/config_json_fwd.json -s . --verbose=yes
|
||||||
|
|
||||||
|
# copy json_literals.hpp
|
||||||
|
$(AMALGAMATED_LITERALS_FILE): include/nlohmann/json_literals.hpp
|
||||||
|
cp include/nlohmann/json_literals.hpp $(AMALGAMATED_LITERALS_FILE)
|
||||||
|
|
||||||
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
|
# check if file single_include/nlohmann/json.hpp has been amalgamated from the nlohmann sources
|
||||||
# Note: this target is called by Travis
|
# Note: this target is called by Travis
|
||||||
check-amalgamation:
|
check-amalgamation:
|
||||||
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
|
@mv $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~
|
||||||
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
|
@mv $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~
|
||||||
|
@mv $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~
|
||||||
@$(MAKE) amalgamate
|
@$(MAKE) amalgamate
|
||||||
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
|
@diff $(AMALGAMATED_FILE) $(AMALGAMATED_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE) ; false)
|
||||||
@diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
|
@diff $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_FWD_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE) ; false)
|
||||||
|
@diff $(AMALGAMATED_LITERALS_FILE) $(AMALGAMATED_LITERALS_FILE)~ || (echo "===================================================================\n Amalgamation required! Please read the contribution guidelines\n in file .github/CONTRIBUTING.md.\n===================================================================" ; mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE) ; false)
|
||||||
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
|
@mv $(AMALGAMATED_FILE)~ $(AMALGAMATED_FILE)
|
||||||
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
|
@mv $(AMALGAMATED_FWD_FILE)~ $(AMALGAMATED_FWD_FILE)
|
||||||
|
@mv $(AMALGAMATED_LITERALS_FILE)~ $(AMALGAMATED_LITERALS_FILE)
|
||||||
@mv BUILD.bazel BUILD.bazel~
|
@mv BUILD.bazel BUILD.bazel~
|
||||||
@$(MAKE) BUILD.bazel
|
@$(MAKE) BUILD.bazel
|
||||||
@diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
|
@diff BUILD.bazel BUILD.bazel~ || (echo "===================================================================\n BUILD.bazel is out of date! Please run 'make BUILD.bazel'.\n===================================================================" ; mv BUILD.bazel~ BUILD.bazel ; false)
|
||||||
@@ -222,7 +231,7 @@ json.tar.xz:
|
|||||||
# We use `-X` to make the resulting ZIP file reproducible, see
|
# We use `-X` to make the resulting ZIP file reproducible, see
|
||||||
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
# <https://content.pivotal.io/blog/barriers-to-deterministic-reproducible-zip-files>.
|
||||||
include.zip: BUILD.bazel
|
include.zip: BUILD.bazel
|
||||||
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
zip -9 --recurse-paths -X include.zip $(SRCS) $(AMALGAMATED_FILE) $(AMALGAMATED_FWD_FILE) $(AMALGAMATED_LITERALS_FILE) BUILD.bazel MODULE.bazel meson.build LICENSE.MIT
|
||||||
|
|
||||||
# Create the files for a release and add signatures and hashes.
|
# Create the files for a release and add signatures and hashes.
|
||||||
release: include.zip json.tar.xz
|
release: include.zip json.tar.xz
|
||||||
@@ -231,10 +240,12 @@ release: include.zip json.tar.xz
|
|||||||
gpg --armor --detach-sig include.zip
|
gpg --armor --detach-sig include.zip
|
||||||
gpg --armor --detach-sig $(AMALGAMATED_FILE)
|
gpg --armor --detach-sig $(AMALGAMATED_FILE)
|
||||||
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
|
gpg --armor --detach-sig $(AMALGAMATED_FWD_FILE)
|
||||||
|
gpg --armor --detach-sig $(AMALGAMATED_LITERALS_FILE)
|
||||||
gpg --armor --detach-sig json.tar.xz
|
gpg --armor --detach-sig json.tar.xz
|
||||||
cp $(AMALGAMATED_FILE) release_files
|
cp $(AMALGAMATED_FILE) release_files
|
||||||
cp $(AMALGAMATED_FWD_FILE) release_files
|
cp $(AMALGAMATED_FWD_FILE) release_files
|
||||||
mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
|
cp $(AMALGAMATED_LITERALS_FILE) release_files
|
||||||
|
mv $(AMALGAMATED_FILE).asc $(AMALGAMATED_FWD_FILE).asc $(AMALGAMATED_LITERALS_FILE).asc json.tar.xz json.tar.xz.asc include.zip include.zip.asc release_files
|
||||||
cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt
|
cd release_files ; shasum -a 256 json.hpp include.zip json.tar.xz > hashes.txt
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+4
-1
@@ -373,9 +373,10 @@ file(GLOB_RECURSE INDENT_FILES
|
|||||||
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
set(include_dir ${PROJECT_SOURCE_DIR}/single_include/nlohmann)
|
||||||
set(tool_dir ${PROJECT_SOURCE_DIR}/tools/amalgamate)
|
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 rm -fr ${include_dir}/json.hpp~ ${include_dir}/json_fwd.hpp~ ${include_dir}/json_literals.hpp~
|
||||||
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
COMMAND cp ${include_dir}/json.hpp ${include_dir}/json.hpp~
|
||||||
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
COMMAND cp ${include_dir}/json_fwd.hpp ${include_dir}/json_fwd.hpp~
|
||||||
|
COMMAND cp ${include_dir}/json_literals.hpp ${include_dir}/json_literals.hpp~
|
||||||
|
|
||||||
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
COMMAND ${Python3_EXECUTABLE} -mvenv venv_astyle
|
||||||
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
COMMAND venv_astyle/bin/pip3 --quiet install -r ${CMAKE_SOURCE_DIR}/tools/astyle/requirements.txt
|
||||||
@@ -383,10 +384,12 @@ add_custom_target(ci_test_amalgamation
|
|||||||
|
|
||||||
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.json -s .
|
||||||
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
COMMAND ${Python3_EXECUTABLE} ${tool_dir}/amalgamate.py -c ${tool_dir}/config_json_fwd.json -s .
|
||||||
|
COMMAND cp ${PROJECT_SOURCE_DIR}/include/nlohmann/json_literals.hpp ${include_dir}/json_literals.hpp
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=none ${include_dir}/json.hpp ${include_dir}/json_fwd.hpp
|
||||||
|
|
||||||
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
COMMAND diff ${include_dir}/json.hpp~ ${include_dir}/json.hpp
|
||||||
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
COMMAND diff ${include_dir}/json_fwd.hpp~ ${include_dir}/json_fwd.hpp
|
||||||
|
COMMAND diff ${include_dir}/json_literals.hpp~ ${include_dir}/json_literals.hpp
|
||||||
|
|
||||||
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
COMMAND venv_astyle/bin/astyle --project=tools/astyle/.astylerc --suffix=orig ${INDENT_FILES}
|
||||||
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
COMMAND for FILE in `find . -name '*.orig'`\; do false \; done
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ header. See also the [macro overview page](../../features/macros.md).
|
|||||||
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
- [**JSON_HAS_RANGES**](json_has_ranges.md) - control `std::ranges` support
|
||||||
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
- [**JSON_HAS_STD_FORMAT**](json_has_std_format.md) - control `std::format`/`std::formatter` support
|
||||||
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
- [**JSON_HAS_THREE_WAY_COMPARISON**](json_has_three_way_comparison.md) - control 3-way comparison support
|
||||||
|
- [**JSON_NO_AUTOMATIC_UDLS**](json_no_automatic_udls.md) - do not include the user-defined string literals (UDLs) automatically
|
||||||
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
- [**JSON_NO_IO**](json_no_io.md) - switch off functions relying on certain C++ I/O headers
|
||||||
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
- [**JSON_NO_THREAD_LOCAL**](json_no_thread_local.md) - switch off the use of `thread_local` storage
|
||||||
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
- [**JSON_SKIP_UNSUPPORTED_COMPILER_CHECK**](json_skip_unsupported_compiler_check.md) - do not warn about unsupported compilers
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# JSON_NO_AUTOMATIC_UDLS
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#define JSON_NO_AUTOMATIC_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
When defined, `<nlohmann/json.hpp>` does not include `<nlohmann/json_literals.hpp>`, so the user-defined string
|
||||||
|
literals [`operator""_json`](../operator_literal_json.md) and
|
||||||
|
[`operator""_json_pointer`](../operator_literal_json_pointer.md) are not declared. Include
|
||||||
|
`<nlohmann/json_literals.hpp>` in the files that use them.
|
||||||
|
|
||||||
|
The literals are ordinary inline functions whose bodies call the parser, so every translation unit that includes them
|
||||||
|
instantiates the parser — even if it never parses anything itself. Defining `JSON_NO_AUTOMATIC_UDLS` for a whole project
|
||||||
|
avoids this cost in translation units that do not parse (e.g., ones that only define types and conversions or pass
|
||||||
|
`json` values around) and reduces their compile time.
|
||||||
|
|
||||||
|
## Default definition
|
||||||
|
|
||||||
|
By default, `#!cpp JSON_NO_AUTOMATIC_UDLS` is not defined, and `<nlohmann/json.hpp>` includes
|
||||||
|
`<nlohmann/json_literals.hpp>`.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#undef JSON_NO_AUTOMATIC_UDLS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
!!! info "Header `<nlohmann/json_literals.hpp>`"
|
||||||
|
|
||||||
|
The header includes `<nlohmann/json.hpp>` itself and places the literals according to
|
||||||
|
[`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md). It is part of the multi-header sources (`include/nlohmann`)
|
||||||
|
and of the single-header sources (`single_include/nlohmann`), next to `json.hpp`.
|
||||||
|
|
||||||
|
!!! info "C++ modules"
|
||||||
|
|
||||||
|
The `nlohmann.json` [module](../../features/modules.md) always exports the literals, regardless of this macro.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
??? example
|
||||||
|
|
||||||
|
The code below includes the library without the literals and adds them in a single translation unit.
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
// compiled with -DJSON_NO_AUTOMATIC_UDLS for the whole project
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
// this file uses the literals, so it includes them explicitly
|
||||||
|
#include <nlohmann/json_literals.hpp>
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
auto j = R"({"foo": 42})"_json;
|
||||||
|
return j.at("/foo"_json_pointer) == 42 ? 0 : 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Without the include of `<nlohmann/json_literals.hpp>`, the code would fail to compile.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_USE_GLOBAL_UDLS`](json_use_global_udls.md) - place user-defined string literals (UDLs) into the global namespace
|
||||||
|
- [Compile times](../../integration/compile_times.md) - options to reduce compile times
|
||||||
|
|
||||||
|
## Version history
|
||||||
|
|
||||||
|
- Added in version 3.13.0.
|
||||||
@@ -15,7 +15,7 @@ The default value is `1`.
|
|||||||
#define JSON_USE_GLOBAL_UDLS 1
|
#define JSON_USE_GLOBAL_UDLS 1
|
||||||
```
|
```
|
||||||
|
|
||||||
When the macro is not defined, the library will define it to its default value.
|
When the macro is not defined, the library behaves as if it were defined to its default value.
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
@@ -32,6 +32,11 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
[`JSON_GlobalUDLs`](../../integration/cmake.md#json_globaludls) (`ON` by default) which defines
|
||||||
`JSON_USE_GLOBAL_UDLS` accordingly.
|
`JSON_USE_GLOBAL_UDLS` accordingly.
|
||||||
|
|
||||||
|
!!! info "Leaving out the literals"
|
||||||
|
|
||||||
|
If [`JSON_NO_AUTOMATIC_UDLS`](json_no_automatic_udls.md) is defined, the literals are only declared where
|
||||||
|
`<nlohmann/json_literals.hpp>` is included; this macro then applies to that header.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
??? example "Example 1: Default behavior"
|
??? example "Example 1: Default behavior"
|
||||||
@@ -92,6 +97,7 @@ When the macro is not defined, the library will define it to its default value.
|
|||||||
|
|
||||||
- [`operator""_json`](../operator_literal_json.md)
|
- [`operator""_json`](../operator_literal_json.md)
|
||||||
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
- [`operator""_json_pointer`](../operator_literal_json_pointer.md)
|
||||||
|
- [`JSON_NO_AUTOMATIC_UDLS`](json_no_automatic_udls.md) - do not include the user-defined string literals automatically
|
||||||
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
- [:simple-cmake: JSON_GlobalUDLs](../../integration/cmake.md#json_globaludls) - CMake option to control the macro
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ using namespace nlohmann;
|
|||||||
```
|
```
|
||||||
|
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is declared in header
|
||||||
|
`<nlohmann/json_literals.hpp>`, which `<nlohmann/json.hpp>` includes unless
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](macros/json_no_automatic_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -59,6 +61,8 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
- [Creating JSON values](../features/creating_values.md) - the article on creating JSON values
|
||||||
|
- [JSON_NO_AUTOMATIC_UDLS](macros/json_no_automatic_udls.md) - do not include the user-defined string literals
|
||||||
|
automatically
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,9 @@ using namespace nlohmann::literals::json_literals;
|
|||||||
using namespace nlohmann;
|
using namespace nlohmann;
|
||||||
```
|
```
|
||||||
This is suggested to ease migration to the next major version release of the library. See
|
This is suggested to ease migration to the next major version release of the library. See
|
||||||
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details.
|
[`JSON_USE_GLOBAL_UDLS`](macros/json_use_global_udls.md#notes) for details. The operator is declared in header
|
||||||
|
`<nlohmann/json_literals.hpp>`, which `<nlohmann/json.hpp>` includes unless
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](macros/json_no_automatic_udls.md) is defined.
|
||||||
|
|
||||||
## Parameters
|
## Parameters
|
||||||
|
|
||||||
@@ -58,6 +60,8 @@ Linear.
|
|||||||
## See also
|
## See also
|
||||||
|
|
||||||
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
- [json_pointer](json_pointer/index.md) - type to represent JSON Pointers
|
||||||
|
- [JSON_NO_AUTOMATIC_UDLS](macros/json_no_automatic_udls.md) - do not include the user-defined string literals
|
||||||
|
automatically
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
|
|||||||
@@ -28,11 +28,6 @@ A minimal map-like container that preserves insertion order for use within [`nlo
|
|||||||
The type uses a `std::vector` to store object elements. Therefore, adding elements can yield a reallocation in which
|
The type uses a `std::vector` to store object elements. Therefore, adding elements can yield a reallocation in which
|
||||||
case all iterators (including the `end()` iterator) and all references to the elements are invalidated.
|
case all iterators (including the `end()` iterator) and all references to the elements are invalidated.
|
||||||
|
|
||||||
When the storage grows, the keys are copied and the mapped values are moved to the new storage. A plain `std::vector`
|
|
||||||
would copy the whole elements instead, because their `#!cpp const` keys make them not nothrow move constructible; for
|
|
||||||
[`ordered_json`](ordered_json.md), this would be a deep copy of every nested value. The values are only copied if
|
|
||||||
`T` is not default constructible or not nothrow move assignable.
|
|
||||||
|
|
||||||
## Member types
|
## Member types
|
||||||
|
|
||||||
- **key_type** - key type (`Key`)
|
- **key_type** - key type (`Key`)
|
||||||
@@ -61,11 +56,6 @@ std::equal_to<> // since C++14
|
|||||||
- **find**
|
- **find**
|
||||||
- **insert**
|
- **insert**
|
||||||
|
|
||||||
## Exception safety
|
|
||||||
|
|
||||||
**emplace**, **operator\[\]**, and **insert(value)** have the strong exception guarantee: if an exception is thrown (for
|
|
||||||
instance, because copying a key or allocating memory fails), the contents of the container are unchanged.
|
|
||||||
|
|
||||||
## Complexity
|
## Complexity
|
||||||
|
|
||||||
Because the elements are stored in a `std::vector` in insertion order, there is no index to look a key up by. Every
|
Because the elements are stored in a `std::vector` in insertion order, there is no index to look a key up by. Every
|
||||||
@@ -132,4 +122,3 @@ This differs from `#!cpp std::map`, where the same operations are O(log n).
|
|||||||
|
|
||||||
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
- Added in version 3.9.0 to implement [`nlohmann::ordered_json`](ordered_json.md).
|
||||||
- Added **key_compare** member in version 3.11.0.
|
- Added **key_compare** member in version 3.11.0.
|
||||||
- Changed in version 3.13.0: growing the storage moves the mapped values instead of copying them.
|
|
||||||
|
|||||||
@@ -83,6 +83,15 @@ When defined, default parse and serialize functions for enums are excluded and h
|
|||||||
|
|
||||||
See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md).
|
See [full documentation of `JSON_DISABLE_ENUM_SERIALIZATION`](../api/macros/json_disable_enum_serialization.md).
|
||||||
|
|
||||||
|
## `JSON_NO_AUTOMATIC_UDLS`
|
||||||
|
|
||||||
|
When defined, `<nlohmann/json.hpp>` does not include `<nlohmann/json_literals.hpp>` with the user-defined string literals
|
||||||
|
`operator""_json` and `operator""_json_pointer`. This reduces the compile time of translation units that do not use
|
||||||
|
them, because the literals instantiate the parser in every translation unit that includes them. Include
|
||||||
|
`<nlohmann/json_literals.hpp>` where the literals are needed.
|
||||||
|
|
||||||
|
See [full documentation of `JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
||||||
|
|
||||||
## `JSON_NO_IO`
|
## `JSON_NO_IO`
|
||||||
|
|
||||||
When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
|
When defined, headers `<cstdio>`, `<ios>`, `<iosfwd>`, `<istream>`, and `<ostream>` are not included and parse functions
|
||||||
|
|||||||
@@ -40,6 +40,9 @@ Only the following symbols are exported from `nlohmann.json`:
|
|||||||
- `nlohmann::literals::json_literals::operator""_json`
|
- `nlohmann::literals::json_literals::operator""_json`
|
||||||
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
- `nlohmann::literals::json_literals::operator""_json_pointer`
|
||||||
|
|
||||||
|
The module always exports the two user-defined string literals, even if
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) is defined when building it.
|
||||||
|
|
||||||
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
Additionally, the following `nlohmann::detail` symbols are exported, solely to work around an MSVC compilation issue
|
||||||
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
([#3970](https://github.com/nlohmann/json/issues/3970)). They are implementation details, not part of the public API,
|
||||||
and should not be used directly:
|
and should not be used directly:
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
# Compile times
|
||||||
|
|
||||||
|
The library is header-only and makes heavy use of templates, so every translation unit that includes
|
||||||
|
`<nlohmann/json.hpp>` pays for parsing the header and instantiating what it uses. This page lists the options to reduce
|
||||||
|
that cost, ordered by how much they typically save.
|
||||||
|
|
||||||
|
!!! info "Measurements"
|
||||||
|
|
||||||
|
The numbers below are medians of nine runs compiling a single translation unit with `-std=c++17 -c` against the
|
||||||
|
single-header version, with Apple clang and GCC 16 on macOS (Apple silicon). They show the order of magnitude to
|
||||||
|
expect; measure your own code before and after a change.
|
||||||
|
|
||||||
|
## Include `json_fwd.hpp` in headers
|
||||||
|
|
||||||
|
Header files that only need to *name* the `json` type — for function declarations, members held by pointer or
|
||||||
|
reference, or friend declarations — can include `<nlohmann/json_fwd.hpp>` instead of `<nlohmann/json.hpp>`. It only
|
||||||
|
forward-declares `basic_json`, `json`, `ordered_json`, `json_pointer`, and `adl_serializer`. The translation units that
|
||||||
|
actually use the values then include `<nlohmann/json.hpp>`.
|
||||||
|
|
||||||
|
```cpp title="person.hpp"
|
||||||
|
#pragma once
|
||||||
|
#include <nlohmann/json_fwd.hpp>
|
||||||
|
|
||||||
|
struct person;
|
||||||
|
void to_json(nlohmann::json& j, const person& p);
|
||||||
|
void from_json(const nlohmann::json& j, person& p);
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp title="person.cpp"
|
||||||
|
#include "person.hpp"
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
void to_json(nlohmann::json& j, const person& p) { /* ... */ }
|
||||||
|
void from_json(const nlohmann::json& j, person& p) { /* ... */ }
|
||||||
|
```
|
||||||
|
|
||||||
|
| Compiler | `json.hpp` (`-O0`) | `json_fwd.hpp` (`-O0`) | Change |
|
||||||
|
|-------------|-------------------:|-----------------------:|-------:|
|
||||||
|
| Apple clang | 704 ms | 329 ms | −53% |
|
||||||
|
| GCC 16 | 779 ms | 242 ms | −69% |
|
||||||
|
|
||||||
|
This is the most effective option, because it avoids the full header in every translation unit that includes
|
||||||
|
*your* headers.
|
||||||
|
|
||||||
|
## Opt out of the automatic user-defined string literals
|
||||||
|
|
||||||
|
The user-defined string literals [`operator""_json`](../api/operator_literal_json.md) and
|
||||||
|
[`operator""_json_pointer`](../api/operator_literal_json_pointer.md) are ordinary inline functions whose bodies call the
|
||||||
|
parser. As `<nlohmann/json.hpp>` includes them by default, every translation unit instantiates the parser, even if it
|
||||||
|
never parses anything itself.
|
||||||
|
|
||||||
|
Define [`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) for the whole project and include
|
||||||
|
`<nlohmann/json_literals.hpp>` only in the files that use the literals:
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
target_compile_definitions(my_target PRIVATE JSON_NO_AUTOMATIC_UDLS)
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <nlohmann/json_literals.hpp> // only where "..."_json is used
|
||||||
|
```
|
||||||
|
|
||||||
|
The saving applies to translation units that do not parse JSON, for example ones that define types and their
|
||||||
|
conversions or only pass `json` values around:
|
||||||
|
|
||||||
|
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `JSON_NO_AUTOMATIC_UDLS` (`-O0` / `-O2`) | Change |
|
||||||
|
|-------------|------------------|------------------------:|-----------------------------------------:|------------:|
|
||||||
|
| Apple clang | model | 776 ms / 846 ms | 629 ms / 692 ms | −19% / −18% |
|
||||||
|
| GCC 16 | model | 1022 ms / 1120 ms | 882 ms / 965 ms | −14% / −14% |
|
||||||
|
| Apple clang | parsing | 992 ms / 1815 ms | 1006 ms / 1823 ms | +1% / 0% |
|
||||||
|
| GCC 16 | parsing | 2018 ms / 3420 ms | 1990 ms / 3454 ms | −1% / +1% |
|
||||||
|
|
||||||
|
Translation units that include only the header save up to a third. Translation units that parse anyway instantiate
|
||||||
|
the parser regardless and see no difference.
|
||||||
|
|
||||||
|
## Instantiate `basic_json` once
|
||||||
|
|
||||||
|
Each translation unit instantiates the member functions of `nlohmann::json` it uses. An explicit instantiation
|
||||||
|
declaration tells the compiler that the non-template members are instantiated elsewhere, so it can skip them:
|
||||||
|
|
||||||
|
```cpp title="json_instance.hpp"
|
||||||
|
#pragma once
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
extern template class nlohmann::basic_json<>;
|
||||||
|
```
|
||||||
|
|
||||||
|
```cpp title="json_instance.cpp"
|
||||||
|
#include "json_instance.hpp"
|
||||||
|
|
||||||
|
template class nlohmann::basic_json<>;
|
||||||
|
```
|
||||||
|
|
||||||
|
Include `json_instance.hpp` instead of `<nlohmann/json.hpp>` and compile and link `json_instance.cpp` once.
|
||||||
|
|
||||||
|
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `extern template` (`-O0` / `-O2`) | Change |
|
||||||
|
|-------------|---------------------|------------------------:|----------------------------------:|------------:|
|
||||||
|
| Apple clang | parsing | 992 ms / 1815 ms | 953 ms / 1625 ms | −4% / −10% |
|
||||||
|
| GCC 16 | parsing | 2018 ms / 3420 ms | 1522 ms / 2728 ms | −25% / −20% |
|
||||||
|
| Apple clang | `json_instance.cpp` | — | 2166 ms / 4660 ms | — |
|
||||||
|
| GCC 16 | `json_instance.cpp` | — | 5085 ms / 10616 ms | — |
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
- The saving grows with the number of translation units that use `json`, while the instantiation translation unit is
|
||||||
|
compiled only once (and is rarely recompiled, as it does not depend on your code).
|
||||||
|
- Member function templates (such as `get<T>()`, `parse(InputType&&)`, or `value(key, default)`) are not covered by
|
||||||
|
the explicit instantiation and are still instantiated where they are used.
|
||||||
|
- The declaration covers exactly `nlohmann::json`. Add the same lines for `nlohmann::ordered_json`
|
||||||
|
(`nlohmann::basic_json<nlohmann::ordered_map>`) or your own `basic_json` specializations if you use them.
|
||||||
|
|
||||||
|
## Use C++20 modules
|
||||||
|
|
||||||
|
With a toolchain that supports named modules, `import nlohmann.json;` compiles the library once into a module and
|
||||||
|
avoids parsing the header in every translation unit. See [Modules](../features/modules.md) for requirements and known
|
||||||
|
issues. Module support is experimental and currently depends heavily on the compiler version.
|
||||||
|
|
||||||
|
## Use precompiled headers
|
||||||
|
|
||||||
|
Build systems can precompile `<nlohmann/json.hpp>` together with other stable headers, for example with CMake's
|
||||||
|
[`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html):
|
||||||
|
|
||||||
|
```cmake
|
||||||
|
target_precompile_headers(my_target PRIVATE <nlohmann/json.hpp>)
|
||||||
|
```
|
||||||
|
|
||||||
|
This removes the cost of parsing the header, but not of instantiating templates in each translation unit, so it
|
||||||
|
combines well with the options above.
|
||||||
|
|
||||||
|
## Options without effect on compile times
|
||||||
|
|
||||||
|
Some configuration macros change what the library declares, but do not measurably change compile times:
|
||||||
|
|
||||||
|
| Macro | Apple clang, model (`-O0` / `-O2`) | GCC 16, model (`-O0` / `-O2`) |
|
||||||
|
|------------------------------------------------------------------------|-----------------------------------:|------------------------------:|
|
||||||
|
| default | 776 ms / 846 ms | 1022 ms / 1120 ms |
|
||||||
|
| [`JSON_NO_IO`](../api/macros/json_no_io.md) | 764 ms / 836 ms | 1022 ms / 1117 ms |
|
||||||
|
| [`JSON_USE_GLOBAL_UDLS`](../api/macros/json_use_global_udls.md)`=0` | 763 ms / 852 ms | 1019 ms / 1106 ms |
|
||||||
|
|
||||||
|
`JSON_USE_GLOBAL_UDLS` only controls *where* the literals are declared; to avoid their cost, use
|
||||||
|
`JSON_NO_AUTOMATIC_UDLS` instead.
|
||||||
|
|
||||||
|
## See also
|
||||||
|
|
||||||
|
- [`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md) - do not include the user-defined string
|
||||||
|
literals automatically
|
||||||
|
- [Modules](../features/modules.md) - C++20 module support
|
||||||
|
- [Header only](index.md) - including the library
|
||||||
@@ -15,4 +15,7 @@ Clang).
|
|||||||
|
|
||||||
You can further use file
|
You can further use file
|
||||||
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
[`single_include/nlohmann/json_fwd.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_fwd.hpp)
|
||||||
for forward declarations.
|
for forward declarations (see [Compile times](compile_times.md)), and file
|
||||||
|
[`single_include/nlohmann/json_literals.hpp`](https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json_literals.hpp)
|
||||||
|
for the user-defined string literals if you define
|
||||||
|
[`JSON_NO_AUTOMATIC_UDLS`](../api/macros/json_no_automatic_udls.md).
|
||||||
|
|||||||
@@ -106,6 +106,7 @@ nav:
|
|||||||
- integration/cmake.md
|
- integration/cmake.md
|
||||||
- integration/package_managers.md
|
- integration/package_managers.md
|
||||||
- integration/pkg-config.md
|
- integration/pkg-config.md
|
||||||
|
- integration/compile_times.md
|
||||||
- API Documentation:
|
- API Documentation:
|
||||||
- basic_json:
|
- basic_json:
|
||||||
- 'Overview': api/basic_json/index.md
|
- 'Overview': api/basic_json/index.md
|
||||||
@@ -293,6 +294,7 @@ nav:
|
|||||||
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
- 'JSON_HAS_STATIC_RTTI': api/macros/json_has_static_rtti.md
|
||||||
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
- 'JSON_HAS_STD_FORMAT': api/macros/json_has_std_format.md
|
||||||
- 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md
|
- 'JSON_HAS_THREE_WAY_COMPARISON': api/macros/json_has_three_way_comparison.md
|
||||||
|
- 'JSON_NO_AUTOMATIC_UDLS': api/macros/json_no_automatic_udls.md
|
||||||
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
- 'JSON_NOEXCEPTION': api/macros/json_noexception.md
|
||||||
- 'JSON_NO_IO': api/macros/json_no_io.md
|
- 'JSON_NO_IO': api/macros/json_no_io.md
|
||||||
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
- 'JSON_NO_THREAD_LOCAL': api/macros/json_no_thread_local.md
|
||||||
|
|||||||
@@ -915,7 +915,3 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
#ifndef JSON_DISABLE_ENUM_SERIALIZATION
|
#ifndef JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef JSON_USE_GLOBAL_UDLS
|
|
||||||
#define JSON_USE_GLOBAL_UDLS 1
|
|
||||||
#endif
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#undef JSON_INLINE_VARIABLE
|
#undef JSON_INLINE_VARIABLE
|
||||||
#undef JSON_NO_UNIQUE_ADDRESS
|
#undef JSON_NO_UNIQUE_ADDRESS
|
||||||
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
#undef JSON_USE_GLOBAL_UDLS
|
|
||||||
|
|
||||||
#ifndef JSON_TEST_KEEP_MACROS
|
#ifndef JSON_TEST_KEEP_MACROS
|
||||||
#undef JSON_CATCH
|
#undef JSON_CATCH
|
||||||
|
|||||||
@@ -6423,55 +6423,6 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
|||||||
return j.dump();
|
return j.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline namespace literals
|
|
||||||
{
|
|
||||||
inline namespace json_literals
|
|
||||||
{
|
|
||||||
|
|
||||||
/// @brief user-defined string literal for JSON values
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
inline nlohmann::json operator""_json(const char* s, std::size_t n)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
inline nlohmann::json operator"" _json(const char* s, std::size_t n)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return nlohmann::json::parse(s, s + n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__cpp_char8_t)
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
|
||||||
{
|
|
||||||
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
|
||||||
reinterpret_cast<const char*>(s) + n);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @brief user-defined string literal for JSON pointer
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return nlohmann::json::json_pointer(std::string(s, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__cpp_char8_t)
|
|
||||||
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
|
||||||
{
|
|
||||||
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace json_literals
|
|
||||||
} // namespace literals
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -6606,17 +6557,6 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#if JSON_USE_GLOBAL_UDLS
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_unscope.hpp>
|
#include <nlohmann/detail/macro_unscope.hpp>
|
||||||
|
|
||||||
// End of GCC diagnostic pragmas for C++ modules support
|
// End of GCC diagnostic pragmas for C++ modules support
|
||||||
@@ -6624,4 +6564,12 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// The user-defined string literals are in a separate header, because their
|
||||||
|
// bodies instantiate the parser in every translation unit that includes them.
|
||||||
|
// Define JSON_NO_AUTOMATIC_UDLS to include <nlohmann/json_literals.hpp> only
|
||||||
|
// where needed.
|
||||||
|
#ifndef JSON_NO_AUTOMATIC_UDLS
|
||||||
|
#include <nlohmann/json_literals.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
#define INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
// This header is included at the end of <nlohmann/json.hpp> unless
|
||||||
|
// JSON_NO_AUTOMATIC_UDLS is defined, and can be included on its own after that.
|
||||||
|
// Either way, the library's internal macros are no longer defined here (and the
|
||||||
|
// amalgamation inlines macro_scope.hpp only once), so only standard and public
|
||||||
|
// macros may be used below.
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
inline namespace json_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON values
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json operator""_json(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json operator"" _json(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(s, s + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
||||||
|
reinterpret_cast<const char*>(s) + n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON pointer
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json_pointer/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(s, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace json_literals
|
||||||
|
} // namespace literals
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !defined(JSON_USE_GLOBAL_UDLS) || JSON_USE_GLOBAL_UDLS
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
@@ -8,15 +8,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <algorithm> // max, min
|
|
||||||
#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 <tuple> // forward_as_tuple
|
#include <type_traits> // enable_if, is_convertible
|
||||||
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
#include <utility> // pair
|
||||||
#include <utility> // forward, move, pair, piecewise_construct
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
#include <nlohmann/detail/macro_scope.hpp>
|
#include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -81,7 +79,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(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};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,7 +94,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(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};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,7 +368,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(value);
|
Container::push_back(value);
|
||||||
return {--this->end(), true};
|
return {--this->end(), true};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -388,64 +386,6 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
|
||||||
@brief add an element whose key is not yet contained at the end
|
|
||||||
|
|
||||||
A std::vector copies all elements when it grows, because their const keys
|
|
||||||
make them not nothrow move constructible. For ordered_json, this is a deep
|
|
||||||
copy of every value. Where the strong exception guarantee can be kept, grow
|
|
||||||
the storage here instead, copying only the keys and moving the values.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
void append(Args&& ... args)
|
|
||||||
{
|
|
||||||
// evaluated here rather than at class scope, because T is still
|
|
||||||
// incomplete when basic_json instantiates its object_t
|
|
||||||
using move_values = std::integral_constant<bool, detail::conjunction<
|
|
||||||
detail::negation<std::is_nothrow_move_constructible<value_type>>,
|
|
||||||
std::is_copy_constructible<key_type>,
|
|
||||||
detail::is_default_constructible<mapped_type>,
|
|
||||||
std::is_nothrow_move_assignable<mapped_type>>::value>;
|
|
||||||
append_impl(move_values{}, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void append_impl(std::true_type /*unused*/, Args&& ... args)
|
|
||||||
{
|
|
||||||
if (this->size() < this->capacity())
|
|
||||||
{
|
|
||||||
Container::emplace_back(std::forward<Args>(args)...);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. May throw, but only changes tmp: copy the keys, value-initialize
|
|
||||||
// the values, and add the new element. The arguments may refer to
|
|
||||||
// elements of this container, so they are used before any value is
|
|
||||||
// moved out of it.
|
|
||||||
Container tmp(this->get_allocator()); // equal allocators, so swap() is valid
|
|
||||||
tmp.reserve((std::min)(this->max_size(), (std::max)(size_type{1}, 2 * this->size())));
|
|
||||||
for (const auto& element : *this)
|
|
||||||
{
|
|
||||||
tmp.emplace_back(std::piecewise_construct, std::forward_as_tuple(element.first), std::forward_as_tuple());
|
|
||||||
}
|
|
||||||
tmp.emplace_back(std::forward<Args>(args)...);
|
|
||||||
|
|
||||||
// 2. Cannot throw: move the values over and adopt the new storage.
|
|
||||||
auto it = tmp.begin();
|
|
||||||
for (auto& element : *this)
|
|
||||||
{
|
|
||||||
it->second = std::move(element.second);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
Container::swap(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void append_impl(std::false_type /*unused*/, Args&& ... args)
|
|
||||||
{
|
|
||||||
Container::emplace_back(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ nlohmann_json_multiple_headers = declare_dependency(
|
|||||||
if not meson.is_subproject()
|
if not meson.is_subproject()
|
||||||
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
install_headers('single_include/nlohmann/json.hpp', subdir: 'nlohmann')
|
||||||
install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
|
install_headers('single_include/nlohmann/json_fwd.hpp', subdir: 'nlohmann')
|
||||||
|
install_headers('single_include/nlohmann/json_literals.hpp', subdir: 'nlohmann')
|
||||||
|
|
||||||
pkgc = import('pkgconfig')
|
pkgc = import('pkgconfig')
|
||||||
pkgc.generate(name: 'nlohmann_json',
|
pkgc.generate(name: 'nlohmann_json',
|
||||||
|
|||||||
@@ -3327,10 +3327,6 @@ void templated_json_throw(ExceptionType exception)
|
|||||||
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
#define JSON_DISABLE_ENUM_SERIALIZATION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef JSON_USE_GLOBAL_UDLS
|
|
||||||
#define JSON_USE_GLOBAL_UDLS 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if JSON_HAS_THREE_WAY_COMPARISON
|
#if JSON_HAS_THREE_WAY_COMPARISON
|
||||||
#include <compare> // partial_ordering
|
#include <compare> // partial_ordering
|
||||||
#endif
|
#endif
|
||||||
@@ -25768,15 +25764,13 @@ NLOHMANN_JSON_NAMESPACE_END
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#include <algorithm> // max, min
|
|
||||||
#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 <tuple> // forward_as_tuple
|
#include <type_traits> // enable_if, is_convertible
|
||||||
#include <type_traits> // enable_if, integral_constant, is_convertible, is_nothrow_move_constructible
|
#include <utility> // pair
|
||||||
#include <utility> // forward, move, pair, piecewise_construct
|
|
||||||
#include <vector> // vector
|
#include <vector> // vector
|
||||||
|
|
||||||
// #include <nlohmann/detail/macro_scope.hpp>
|
// #include <nlohmann/detail/macro_scope.hpp>
|
||||||
@@ -25843,7 +25837,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(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};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25858,7 +25852,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(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};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26132,7 +26126,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
return {it, false};
|
return {it, false};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
append(value);
|
Container::push_back(value);
|
||||||
return {--this->end(), true};
|
return {--this->end(), true};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26150,64 +26144,6 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
|
||||||
@brief add an element whose key is not yet contained at the end
|
|
||||||
|
|
||||||
A std::vector copies all elements when it grows, because their const keys
|
|
||||||
make them not nothrow move constructible. For ordered_json, this is a deep
|
|
||||||
copy of every value. Where the strong exception guarantee can be kept, grow
|
|
||||||
the storage here instead, copying only the keys and moving the values.
|
|
||||||
*/
|
|
||||||
template<typename... Args>
|
|
||||||
void append(Args&& ... args)
|
|
||||||
{
|
|
||||||
// evaluated here rather than at class scope, because T is still
|
|
||||||
// incomplete when basic_json instantiates its object_t
|
|
||||||
using move_values = std::integral_constant<bool, detail::conjunction<
|
|
||||||
detail::negation<std::is_nothrow_move_constructible<value_type>>,
|
|
||||||
std::is_copy_constructible<key_type>,
|
|
||||||
detail::is_default_constructible<mapped_type>,
|
|
||||||
std::is_nothrow_move_assignable<mapped_type>>::value>;
|
|
||||||
append_impl(move_values{}, std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void append_impl(std::true_type /*unused*/, Args&& ... args)
|
|
||||||
{
|
|
||||||
if (this->size() < this->capacity())
|
|
||||||
{
|
|
||||||
Container::emplace_back(std::forward<Args>(args)...);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1. May throw, but only changes tmp: copy the keys, value-initialize
|
|
||||||
// the values, and add the new element. The arguments may refer to
|
|
||||||
// elements of this container, so they are used before any value is
|
|
||||||
// moved out of it.
|
|
||||||
Container tmp(this->get_allocator()); // equal allocators, so swap() is valid
|
|
||||||
tmp.reserve((std::min)(this->max_size(), (std::max)(size_type{1}, 2 * this->size())));
|
|
||||||
for (const auto& element : *this)
|
|
||||||
{
|
|
||||||
tmp.emplace_back(std::piecewise_construct, std::forward_as_tuple(element.first), std::forward_as_tuple());
|
|
||||||
}
|
|
||||||
tmp.emplace_back(std::forward<Args>(args)...);
|
|
||||||
|
|
||||||
// 2. Cannot throw: move the values over and adopt the new storage.
|
|
||||||
auto it = tmp.begin();
|
|
||||||
for (auto& element : *this)
|
|
||||||
{
|
|
||||||
it->second = std::move(element.second);
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
Container::swap(tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
void append_impl(std::false_type /*unused*/, Args&& ... args)
|
|
||||||
{
|
|
||||||
Container::emplace_back(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -32564,55 +32500,6 @@ std::string format_as(const NLOHMANN_BASIC_JSON_TPL& j)
|
|||||||
return j.dump();
|
return j.dump();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline namespace literals
|
|
||||||
{
|
|
||||||
inline namespace json_literals
|
|
||||||
{
|
|
||||||
|
|
||||||
/// @brief user-defined string literal for JSON values
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
inline nlohmann::json operator""_json(const char* s, std::size_t n)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
inline nlohmann::json operator"" _json(const char* s, std::size_t n)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return nlohmann::json::parse(s, s + n);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__cpp_char8_t)
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
|
||||||
{
|
|
||||||
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
|
||||||
reinterpret_cast<const char*>(s) + n);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// @brief user-defined string literal for JSON pointer
|
|
||||||
/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
|
|
||||||
JSON_HEDLEY_NON_NULL(1)
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
return nlohmann::json::json_pointer(std::string(s, n));
|
|
||||||
}
|
|
||||||
|
|
||||||
#if defined(__cpp_char8_t)
|
|
||||||
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
|
||||||
{
|
|
||||||
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} // namespace json_literals
|
|
||||||
} // namespace literals
|
|
||||||
NLOHMANN_JSON_NAMESPACE_END
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
///////////////////////
|
///////////////////////
|
||||||
@@ -32747,17 +32634,6 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
|
|
||||||
} // namespace std
|
} // namespace std
|
||||||
|
|
||||||
#if JSON_USE_GLOBAL_UDLS
|
|
||||||
#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
|
|
||||||
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
#else
|
|
||||||
// GCC 4.8 requires a space between "" and suffix
|
|
||||||
using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// #include <nlohmann/detail/macro_unscope.hpp>
|
// #include <nlohmann/detail/macro_unscope.hpp>
|
||||||
// __ _____ _____ _____
|
// __ _____ _____ _____
|
||||||
// __| | __| | | | JSON for Modern C++
|
// __| | __| | | | JSON for Modern C++
|
||||||
@@ -32786,7 +32662,6 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
#undef JSON_INLINE_VARIABLE
|
#undef JSON_INLINE_VARIABLE
|
||||||
#undef JSON_NO_UNIQUE_ADDRESS
|
#undef JSON_NO_UNIQUE_ADDRESS
|
||||||
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
#undef JSON_DISABLE_ENUM_SERIALIZATION
|
||||||
#undef JSON_USE_GLOBAL_UDLS
|
|
||||||
|
|
||||||
#ifndef JSON_TEST_KEEP_MACROS
|
#ifndef JSON_TEST_KEEP_MACROS
|
||||||
#undef JSON_CATCH
|
#undef JSON_CATCH
|
||||||
@@ -32979,4 +32854,97 @@ struct formatter<nlohmann::NLOHMANN_BASIC_JSON_TPL, char> // NOLINT(cert-dcl58-c
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// The user-defined string literals are in a separate header, because their
|
||||||
|
// bodies instantiate the parser in every translation unit that includes them.
|
||||||
|
// Define JSON_NO_AUTOMATIC_UDLS to include <nlohmann/json_literals.hpp> only
|
||||||
|
// where needed.
|
||||||
|
#ifndef JSON_NO_AUTOMATIC_UDLS
|
||||||
|
// #include <nlohmann/json_literals.hpp>
|
||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
#define INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
|
// #include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// This header is included at the end of <nlohmann/json.hpp> unless
|
||||||
|
// JSON_NO_AUTOMATIC_UDLS is defined, and can be included on its own after that.
|
||||||
|
// Either way, the library's internal macros are no longer defined here (and the
|
||||||
|
// amalgamation inlines macro_scope.hpp only once), so only standard and public
|
||||||
|
// macros may be used below.
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
inline namespace json_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON values
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json operator""_json(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json operator"" _json(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(s, s + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
||||||
|
reinterpret_cast<const char*>(s) + n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON pointer
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json_pointer/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(s, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace json_literals
|
||||||
|
} // namespace literals
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !defined(JSON_USE_GLOBAL_UDLS) || JSON_USE_GLOBAL_UDLS
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
#endif // INCLUDE_NLOHMANN_JSON_HPP_
|
||||||
|
|||||||
@@ -0,0 +1,83 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
#ifndef INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
#define INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
|
|
||||||
|
#include <cstddef> // size_t
|
||||||
|
#include <string> // string
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
// This header is included at the end of <nlohmann/json.hpp> unless
|
||||||
|
// JSON_NO_AUTOMATIC_UDLS is defined, and can be included on its own after that.
|
||||||
|
// Either way, the library's internal macros are no longer defined here (and the
|
||||||
|
// amalgamation inlines macro_scope.hpp only once), so only standard and public
|
||||||
|
// macros may be used below.
|
||||||
|
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
inline namespace literals
|
||||||
|
{
|
||||||
|
inline namespace json_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON values
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json operator""_json(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json operator"" _json(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(s, s + n);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json operator""_json(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::parse(reinterpret_cast<const char*>(s),
|
||||||
|
reinterpret_cast<const char*>(s) + n);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief user-defined string literal for JSON pointer
|
||||||
|
/// @sa https://json.nlohmann.me/api/operator_literal_json_pointer/
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char* s, std::size_t n)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
inline nlohmann::json::json_pointer operator"" _json_pointer(const char* s, std::size_t n)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(s, n));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(__cpp_char8_t)
|
||||||
|
inline nlohmann::json::json_pointer operator""_json_pointer(const char8_t* s, std::size_t n)
|
||||||
|
{
|
||||||
|
return nlohmann::json::json_pointer(std::string(reinterpret_cast<const char*>(s), n));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace json_literals
|
||||||
|
} // namespace literals
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
#if !defined(JSON_USE_GLOBAL_UDLS) || JSON_USE_GLOBAL_UDLS
|
||||||
|
#if !defined(__GNUC__) || defined(__clang__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#else
|
||||||
|
// GCC 4.8 requires a space between "" and suffix
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
using nlohmann::literals::json_literals::operator"" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // INCLUDE_NLOHMANN_JSON_LITERALS_HPP_
|
||||||
@@ -18,6 +18,7 @@ module;
|
|||||||
// See: https://github.com/nlohmann/json/issues/5103
|
// See: https://github.com/nlohmann/json/issues/5103
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <nlohmann/json_literals.hpp>
|
||||||
|
|
||||||
export module nlohmann.json;
|
export module nlohmann.json;
|
||||||
|
|
||||||
|
|||||||
@@ -119,39 +119,6 @@ BENCHMARK_CAPTURE(ParseIndented, canada / 4, TEST_DATA_DIRECTORY "/nativej
|
|||||||
BENCHMARK_CAPTURE(ParseIndented, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
|
BENCHMARK_CAPTURE(ParseIndented, citm_catalog / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json", 4);
|
||||||
BENCHMARK_CAPTURE(ParseIndented, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
|
BENCHMARK_CAPTURE(ParseIndented, twitter / 4, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json", 4);
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
// parse JSON from string into an ordered_json
|
|
||||||
//
|
|
||||||
// Same as ParseString above, but with nlohmann::ordered_json, whose objects
|
|
||||||
// keep their members in a vector: the pair of rows shows what preserving the
|
|
||||||
// insertion order costs.
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static void ParseStringOrdered(benchmark::State& state, const char* filename)
|
|
||||||
{
|
|
||||||
std::ifstream f(filename);
|
|
||||||
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
|
||||||
|
|
||||||
while (state.KeepRunning())
|
|
||||||
{
|
|
||||||
state.PauseTiming();
|
|
||||||
auto* j = new nlohmann::ordered_json();
|
|
||||||
state.ResumeTiming();
|
|
||||||
|
|
||||||
*j = nlohmann::ordered_json::parse(str);
|
|
||||||
|
|
||||||
state.PauseTiming();
|
|
||||||
delete j;
|
|
||||||
state.ResumeTiming();
|
|
||||||
}
|
|
||||||
|
|
||||||
state.SetBytesProcessed(state.iterations() * str.size());
|
|
||||||
}
|
|
||||||
BENCHMARK_CAPTURE(ParseStringOrdered, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
|
||||||
BENCHMARK_CAPTURE(ParseStringOrdered, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
|
||||||
BENCHMARK_CAPTURE(ParseStringOrdered, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
|
||||||
BENCHMARK_CAPTURE(ParseStringOrdered, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
// serialize JSON
|
// serialize JSON
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -46,24 +46,6 @@ TEST_CASE("Tests with disabled exceptions")
|
|||||||
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 == "[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)
|
delete sax_no_exception::error_string; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("growing an ordered_json object")
|
|
||||||
{
|
|
||||||
auto j = nlohmann::ordered_json::object();
|
|
||||||
for (int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
j[std::to_string(i)] = {{"nested", i}};
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(j.size() == 100);
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& element : j.items())
|
|
||||||
{
|
|
||||||
CHECK(element.key() == std::to_string(i));
|
|
||||||
CHECK(element.value()["nested"] == i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DOCTEST_GCC_SUPPRESS_WARNING_POP
|
DOCTEST_GCC_SUPPRESS_WARNING_POP
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
// __ _____ _____ _____
|
||||||
|
// __| | __| | | | JSON for Modern C++ (supporting code)
|
||||||
|
// | | |__ | | | | | | version 3.12.0
|
||||||
|
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
//
|
||||||
|
// SPDX-FileCopyrightText: 2013-2026 Niels Lohmann <https://nlohmann.me>
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
// This translation unit checks JSON_NO_AUTOMATIC_UDLS, which keeps
|
||||||
|
// <nlohmann/json.hpp> from including <nlohmann/json_literals.hpp> and thereby
|
||||||
|
// leaves out the user-defined string literals operator""_json and
|
||||||
|
// operator""_json_pointer (see #5294), and that including
|
||||||
|
// <nlohmann/json_literals.hpp> afterwards brings them back.
|
||||||
|
#define JSON_NO_AUTOMATIC_UDLS 1
|
||||||
|
|
||||||
|
#include "doctest_compatibility.h"
|
||||||
|
|
||||||
|
#include <cstddef>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
// An argument type whose associated namespace is the library namespace, so
|
||||||
|
// argument-dependent lookup of a literal operator called by its function name
|
||||||
|
// also searches the inline namespaces nlohmann::literals::json_literals.
|
||||||
|
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||||
|
struct no_automatic_udls_probe
|
||||||
|
{
|
||||||
|
operator const char* () const // NOLINT(google-explicit-constructor,hicpp-explicit-conversions)
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
NLOHMANN_JSON_NAMESPACE_END
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
// The calls below use a dependent argument, so a literal operator that is not
|
||||||
|
// declared at all is a substitution failure rather than a hard error: lookup is
|
||||||
|
// deferred to the point of instantiation, where it considers the declarations
|
||||||
|
// visible from here (the global using-declarations of JSON_USE_GLOBAL_UDLS) plus
|
||||||
|
// argument-dependent lookup (the literals in the library namespace).
|
||||||
|
template<typename T>
|
||||||
|
using json_udl_t = decltype(operator""_json(std::declval<T>(), std::size_t()));
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using json_pointer_udl_t = decltype(operator""_json_pointer(std::declval<T>(), std::size_t()));
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using has_json_udl = nlohmann::detail::is_detected<json_udl_t, T>;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using has_json_pointer_udl = nlohmann::detail::is_detected<json_pointer_udl_t, T>;
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST_CASE("JSON_NO_AUTOMATIC_UDLS")
|
||||||
|
{
|
||||||
|
SECTION("literals are not declared")
|
||||||
|
{
|
||||||
|
// global namespace (JSON_USE_GLOBAL_UDLS defaults to 1)
|
||||||
|
CHECK_FALSE(has_json_udl<const char*>::value);
|
||||||
|
CHECK_FALSE(has_json_pointer_udl<const char*>::value);
|
||||||
|
|
||||||
|
// nlohmann::literals::json_literals
|
||||||
|
CHECK_FALSE(has_json_udl<nlohmann::no_automatic_udls_probe>::value);
|
||||||
|
CHECK_FALSE(has_json_pointer_udl<nlohmann::no_automatic_udls_probe>::value);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("the rest of the library keeps working")
|
||||||
|
{
|
||||||
|
const json j = json::parse(R"({"foo": {"bar": 42}})");
|
||||||
|
CHECK(j.dump() == R"({"foo":{"bar":42}})");
|
||||||
|
|
||||||
|
const json::json_pointer ptr("/foo/bar");
|
||||||
|
CHECK(j.at(ptr) == 42);
|
||||||
|
CHECK(j.contains(ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the literals can still be added where they are needed
|
||||||
|
#include <nlohmann/json_literals.hpp>
|
||||||
|
|
||||||
|
TEST_CASE("JSON_NO_AUTOMATIC_UDLS with <nlohmann/json_literals.hpp>")
|
||||||
|
{
|
||||||
|
SECTION("global namespace")
|
||||||
|
{
|
||||||
|
CHECK("[1,2]"_json == json({1, 2}));
|
||||||
|
CHECK("/a/0"_json_pointer == json::json_pointer("/a/0"));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("nlohmann::literals::json_literals")
|
||||||
|
{
|
||||||
|
using namespace nlohmann::literals::json_literals; // NOLINT(google-build-using-namespace)
|
||||||
|
CHECK(R"({"a":[42]})"_json.at("/a/0"_json_pointer) == 42);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,87 +11,6 @@
|
|||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
using nlohmann::ordered_map;
|
using nlohmann::ordered_map;
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <string>
|
|
||||||
#include <type_traits>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace
|
|
||||||
{
|
|
||||||
// number of copies made of counted values
|
|
||||||
int value_copies = 0;
|
|
||||||
|
|
||||||
// a mapped type that counts its copies; moving from it leaves -1 behind
|
|
||||||
struct counted // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
|
||||||
{
|
|
||||||
int payload = 0;
|
|
||||||
|
|
||||||
counted() = default;
|
|
||||||
explicit counted(int p) noexcept : payload(p) {}
|
|
||||||
counted(const counted& other) : payload(other.payload)
|
|
||||||
{
|
|
||||||
++value_copies;
|
|
||||||
}
|
|
||||||
counted(counted&& other) noexcept : payload(other.payload)
|
|
||||||
{
|
|
||||||
other.payload = -1;
|
|
||||||
}
|
|
||||||
counted& operator=(const counted&) = delete;
|
|
||||||
counted& operator=(counted&& other) noexcept
|
|
||||||
{
|
|
||||||
payload = other.payload;
|
|
||||||
other.payload = -1;
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#if !defined(JSON_NOEXCEPTION)
|
|
||||||
// number of throwing_key copies that still succeed; the next one throws
|
|
||||||
// (a negative value means that copies never throw)
|
|
||||||
int key_copies_until_throw = -1;
|
|
||||||
|
|
||||||
// a key type whose copy constructor can be made to throw
|
|
||||||
struct throwing_key // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
|
|
||||||
{
|
|
||||||
int id = 0;
|
|
||||||
|
|
||||||
explicit throwing_key(int i) noexcept : id(i) {}
|
|
||||||
throwing_key(const throwing_key& other) : id(other.id)
|
|
||||||
{
|
|
||||||
if (key_copies_until_throw == 0)
|
|
||||||
{
|
|
||||||
throw std::runtime_error("key copy failed");
|
|
||||||
}
|
|
||||||
if (key_copies_until_throw > 0)
|
|
||||||
{
|
|
||||||
--key_copies_until_throw;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throwing_key& operator=(const throwing_key&) = delete;
|
|
||||||
|
|
||||||
friend bool operator==(const throwing_key& lhs, const throwing_key& rhs) noexcept
|
|
||||||
{
|
|
||||||
return lhs.id == rhs.id;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// a mapped type that cannot be default-constructed
|
|
||||||
struct no_default
|
|
||||||
{
|
|
||||||
explicit no_default(int v) noexcept : value(v) {}
|
|
||||||
int value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ordered_json must keep moving its values when an object grows
|
|
||||||
using ordered_object_t = nlohmann::ordered_json::object_t;
|
|
||||||
static_assert(!std::is_nothrow_move_constructible<ordered_object_t::value_type>::value, "std::vector would move the elements itself");
|
|
||||||
static_assert(std::is_copy_constructible<ordered_object_t::key_type>::value, "keys must be copyable");
|
|
||||||
static_assert(std::is_default_constructible<ordered_object_t::mapped_type>::value, "values must be default-constructible");
|
|
||||||
static_assert(std::is_nothrow_move_assignable<ordered_object_t::mapped_type>::value, "values must be nothrow move-assignable");
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
TEST_CASE("ordered_map")
|
TEST_CASE("ordered_map")
|
||||||
{
|
{
|
||||||
SECTION("constructor")
|
SECTION("constructor")
|
||||||
@@ -394,270 +313,3 @@ TEST_CASE("ordered_map")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("ordered_map growth")
|
|
||||||
{
|
|
||||||
SECTION("values are moved, not copied, when the storage grows")
|
|
||||||
{
|
|
||||||
ordered_map<std::string, counted> om;
|
|
||||||
std::size_t growths = 0;
|
|
||||||
value_copies = 0;
|
|
||||||
|
|
||||||
// inserts 100 elements with the given function and counts the growths
|
|
||||||
const auto fill = [&om, &growths](void (*insert)(ordered_map<std::string, counted>&, int))
|
|
||||||
{
|
|
||||||
for (int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
const auto old_capacity = om.capacity();
|
|
||||||
insert(om, i);
|
|
||||||
if (om.capacity() > old_capacity)
|
|
||||||
{
|
|
||||||
++growths;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// checks that the elements are in insertion order with their values
|
|
||||||
const auto check_contents = [&om]
|
|
||||||
{
|
|
||||||
CHECK(om.size() == 100);
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& element : om)
|
|
||||||
{
|
|
||||||
CHECK(element.first == std::to_string(i));
|
|
||||||
CHECK(element.second.payload == i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SECTION("emplace")
|
|
||||||
{
|
|
||||||
fill([](ordered_map<std::string, counted>& m, int i)
|
|
||||||
{
|
|
||||||
m.emplace(std::to_string(i), counted(i));
|
|
||||||
});
|
|
||||||
CHECK(growths >= 3);
|
|
||||||
CHECK(value_copies == 0);
|
|
||||||
check_contents();
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("operator[]")
|
|
||||||
{
|
|
||||||
fill([](ordered_map<std::string, counted>& m, int i)
|
|
||||||
{
|
|
||||||
m[std::to_string(i)] = counted(i);
|
|
||||||
});
|
|
||||||
CHECK(growths >= 3);
|
|
||||||
CHECK(value_copies == 0);
|
|
||||||
check_contents();
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("insert(value_type&&)")
|
|
||||||
{
|
|
||||||
fill([](ordered_map<std::string, counted>& m, int i)
|
|
||||||
{
|
|
||||||
m.insert({std::to_string(i), counted(i)});
|
|
||||||
});
|
|
||||||
CHECK(growths >= 3);
|
|
||||||
CHECK(value_copies == 0);
|
|
||||||
check_contents();
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("insert(const value_type&)")
|
|
||||||
{
|
|
||||||
fill([](ordered_map<std::string, counted>& m, int i)
|
|
||||||
{
|
|
||||||
const std::pair<const std::string, counted> value(std::to_string(i), counted(i));
|
|
||||||
m.insert(value);
|
|
||||||
});
|
|
||||||
CHECK(growths >= 3);
|
|
||||||
// only the inserted values are copied
|
|
||||||
CHECK(value_copies == 100);
|
|
||||||
check_contents();
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("insert(first, last)")
|
|
||||||
{
|
|
||||||
std::vector<std::pair<const std::string, counted>> values;
|
|
||||||
values.reserve(100);
|
|
||||||
for (int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
values.emplace_back(std::to_string(i), counted(i));
|
|
||||||
}
|
|
||||||
value_copies = 0;
|
|
||||||
|
|
||||||
om.insert(values.cbegin(), values.cend());
|
|
||||||
// only the inserted values are copied
|
|
||||||
CHECK(value_copies == 100);
|
|
||||||
check_contents();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("elements keep their order and values over many growths")
|
|
||||||
{
|
|
||||||
ordered_map<std::string, counted> om;
|
|
||||||
for (int i = 0; i < 1000; ++i)
|
|
||||||
{
|
|
||||||
om.emplace(std::to_string(i), counted(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(om.size() == 1000);
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& element : om)
|
|
||||||
{
|
|
||||||
CHECK(element.first == std::to_string(i));
|
|
||||||
CHECK(element.second.payload == i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("arguments may refer to elements of the full container")
|
|
||||||
{
|
|
||||||
SECTION("moving a value out of the container")
|
|
||||||
{
|
|
||||||
ordered_map<std::string, counted> om;
|
|
||||||
om.reserve(4);
|
|
||||||
while (om.size() < om.capacity())
|
|
||||||
{
|
|
||||||
const auto i = static_cast<int>(om.size());
|
|
||||||
om.emplace(std::to_string(i), counted(i));
|
|
||||||
}
|
|
||||||
const auto size = om.size();
|
|
||||||
|
|
||||||
om.emplace("new", std::move(om.at("0")));
|
|
||||||
CHECK(om.size() == size + 1);
|
|
||||||
CHECK(om.at("new").payload == 0);
|
|
||||||
CHECK(om.at("0").payload == -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("using a value as key")
|
|
||||||
{
|
|
||||||
ordered_map<std::string, std::string> om;
|
|
||||||
om.reserve(4);
|
|
||||||
while (om.size() < om.capacity())
|
|
||||||
{
|
|
||||||
const auto i = std::to_string(om.size());
|
|
||||||
om.emplace("k" + i, "v" + i);
|
|
||||||
}
|
|
||||||
const auto size = om.size();
|
|
||||||
|
|
||||||
om.emplace(om.at("k0"), std::string("x"));
|
|
||||||
CHECK(om.size() == size + 1);
|
|
||||||
CHECK(om.at("k0") == "v0");
|
|
||||||
CHECK(om.at("v0") == "x");
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("ordered_json")
|
|
||||||
{
|
|
||||||
auto j = nlohmann::ordered_json::object();
|
|
||||||
auto& object = j.get_ref<nlohmann::ordered_json::object_t&>();
|
|
||||||
object.reserve(4);
|
|
||||||
while (object.size() < object.capacity())
|
|
||||||
{
|
|
||||||
const auto i = std::to_string(object.size());
|
|
||||||
j[i] = "a value that is too long for the small string optimization " + i;
|
|
||||||
}
|
|
||||||
const auto size = j.size();
|
|
||||||
|
|
||||||
j.emplace("new", std::move(j["0"]));
|
|
||||||
CHECK(j.size() == size + 1);
|
|
||||||
CHECK(j["new"] == "a value that is too long for the small string optimization 0");
|
|
||||||
CHECK(j["0"].is_null());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(JSON_NOEXCEPTION)
|
|
||||||
SECTION("the container is unchanged if growing it throws")
|
|
||||||
{
|
|
||||||
ordered_map<throwing_key, counted> om;
|
|
||||||
om.reserve(4);
|
|
||||||
while (om.size() < om.capacity())
|
|
||||||
{
|
|
||||||
const auto i = static_cast<int>(om.size());
|
|
||||||
om.emplace(throwing_key(i), counted(i));
|
|
||||||
}
|
|
||||||
const auto size = om.size();
|
|
||||||
const auto capacity = om.capacity();
|
|
||||||
|
|
||||||
// checks that the elements are unchanged
|
|
||||||
const auto check_unchanged = [&om, size, capacity]
|
|
||||||
{
|
|
||||||
CHECK(om.size() == size);
|
|
||||||
CHECK(om.capacity() == capacity);
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& element : om)
|
|
||||||
{
|
|
||||||
CHECK(element.first.id == i);
|
|
||||||
CHECK(element.second.payload == i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
SECTION("emplace")
|
|
||||||
{
|
|
||||||
// growing copies the existing keys and then the new one; let each of these copies throw
|
|
||||||
for (std::size_t k = 0; k <= size; ++k)
|
|
||||||
{
|
|
||||||
counted value(100);
|
|
||||||
key_copies_until_throw = static_cast<int>(k);
|
|
||||||
CHECK_THROWS_AS(om.emplace(throwing_key(100), std::move(value)), std::runtime_error);
|
|
||||||
key_copies_until_throw = -1;
|
|
||||||
|
|
||||||
check_unchanged();
|
|
||||||
CHECK(value.payload == 100); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved)
|
|
||||||
}
|
|
||||||
|
|
||||||
om.emplace(throwing_key(100), counted(100));
|
|
||||||
CHECK(om.size() == size + 1);
|
|
||||||
CHECK(om.capacity() > capacity);
|
|
||||||
CHECK(om.at(throwing_key(100)).payload == 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("insert(const value_type&)")
|
|
||||||
{
|
|
||||||
const std::pair<const throwing_key, counted> value(throwing_key(100), counted(100));
|
|
||||||
value_copies = 0;
|
|
||||||
|
|
||||||
key_copies_until_throw = static_cast<int>(size / 2);
|
|
||||||
CHECK_THROWS_AS(om.insert(value), std::runtime_error);
|
|
||||||
key_copies_until_throw = -1;
|
|
||||||
|
|
||||||
check_unchanged();
|
|
||||||
CHECK(value_copies == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
SECTION("elements that std::vector moves, or that cannot be moved back")
|
|
||||||
{
|
|
||||||
SECTION("nothrow move-constructible elements")
|
|
||||||
{
|
|
||||||
ordered_map<int, counted> om;
|
|
||||||
value_copies = 0;
|
|
||||||
for (int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
om.emplace(i, counted(i));
|
|
||||||
}
|
|
||||||
CHECK(om.size() == 100);
|
|
||||||
CHECK(value_copies == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SECTION("mapped type without default constructor")
|
|
||||||
{
|
|
||||||
ordered_map<std::string, no_default> om;
|
|
||||||
for (int i = 0; i < 100; ++i)
|
|
||||||
{
|
|
||||||
om.emplace(std::to_string(i), no_default(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK(om.size() == 100);
|
|
||||||
int i = 0;
|
|
||||||
for (const auto& element : om)
|
|
||||||
{
|
|
||||||
CHECK(element.first == std::to_string(i));
|
|
||||||
CHECK(element.second.value == i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user