Merge branch 'develop' of https://github.com/nlohmann/json into reuse
This commit is contained in:
commit
71aa668658
3
.gitignore
vendored
3
.gitignore
vendored
@ -9,9 +9,10 @@
|
||||
|
||||
/.idea
|
||||
/cmake-build-*
|
||||
|
||||
# Visual Studio Code
|
||||
/.vs/
|
||||
/.vscode/
|
||||
/out/
|
||||
|
||||
# clangd cache
|
||||
/.cache/
|
||||
|
||||
64
README.md
64
README.md
@ -13,6 +13,7 @@
|
||||
[](https://json.nlohmann.me)
|
||||
[](https://raw.githubusercontent.com/nlohmann/json/master/LICENSE.MIT)
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
[](https://repology.org/project/nlohmann-json/versions)
|
||||
[](https://github.com/nlohmann/json/releases)
|
||||
[](https://github.com/nlohmann/json/issues)
|
||||
[](https://isitmaintained.com/project/nlohmann/json "Average time to resolve an issue")
|
||||
@ -24,6 +25,8 @@
|
||||
- [Sponsors](#sponsors)
|
||||
- [Support](#support) ([documentation](https://json.nlohmann.me), [FAQ](https://json.nlohmann.me/home/faq/), [discussions](https://github.com/nlohmann/json/discussions), [API](https://json.nlohmann.me/api/basic_json/), [bug issues](https://github.com/nlohmann/json/issues))
|
||||
- [Examples](#examples)
|
||||
- [Read JSON from a file](#read-json-from-a-file)
|
||||
- [Creating `json` objects from JSON literals](#creating-json-objects-from-json-literals)
|
||||
- [JSON as first-class data type](#json-as-first-class-data-type)
|
||||
- [Serialization / Deserialization](#serialization--deserialization)
|
||||
- [STL-like access](#stl-like-access)
|
||||
@ -98,7 +101,66 @@ There is also a [**docset**](https://github.com/Kapeli/Dash-User-Contributions/t
|
||||
|
||||
## Examples
|
||||
|
||||
Beside the examples below, you may want to check the [documentation](https://json.nlohmann.me/) where each function contains a separate code example (e.g., check out [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/)). All [example files](https://github.com/nlohmann/json/tree/develop/docs/examples) can be compiled and executed on their own (e.g., file [emplace.cpp](https://github.com/nlohmann/json/blob/develop/docs/examples/emplace.cpp)).
|
||||
Here are some examples to give you an idea how to use the class.
|
||||
|
||||
Beside the examples below, you may want to:
|
||||
|
||||
→ Check the [documentation](https://json.nlohmann.me/)\
|
||||
→ Browse the [standalone example files](https://github.com/nlohmann/json/tree/develop/docs/examples)
|
||||
|
||||
Every API function (documented in the [API Documentation](https://json.nlohmann.me/api/basic_json/)) has a corresponding standalone example file. For example, the [`emplace()`](https://json.nlohmann.me/api/basic_json/emplace/) function has a matching [emplace.cpp](https://github.com/nlohmann/json/blob/develop/docs/examples/emplace.cpp) example file.
|
||||
|
||||
### Read JSON from a file
|
||||
|
||||
The `json` class provides an API for manipulating a JSON value. To create a `json` object by reading a JSON file:
|
||||
|
||||
```cpp
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
using json = nlohmann::json;
|
||||
|
||||
// ...
|
||||
|
||||
std::ifstream f("example.json");
|
||||
json data = json::parse(f);
|
||||
```
|
||||
|
||||
### Creating `json` objects from JSON literals
|
||||
|
||||
Assume you want to create hard-code this literal JSON value in a file, as a `json` object:
|
||||
|
||||
```json
|
||||
{
|
||||
"pi": 3.141,
|
||||
"happy": true
|
||||
}
|
||||
```
|
||||
|
||||
There are various options:
|
||||
|
||||
```cpp
|
||||
// Using (raw) string literals and json::parse
|
||||
json ex1 = json::parse(R"(
|
||||
{
|
||||
"pi": 3.141,
|
||||
"happy": true
|
||||
}
|
||||
)");
|
||||
|
||||
// Using user-defined (raw) string literals
|
||||
json ex2 = R"(
|
||||
{
|
||||
"pi": 3.141,
|
||||
"happy": true
|
||||
}
|
||||
)"_json;
|
||||
|
||||
// Using initializer lists
|
||||
json ex3 = {
|
||||
{"happy", true},
|
||||
{"pi", 3.141},
|
||||
};
|
||||
```
|
||||
|
||||
### JSON as first-class data type
|
||||
|
||||
|
||||
@ -595,7 +595,7 @@ add_custom_target(ci_test_amalgamation
|
||||
add_custom_target(ci_test_single_header
|
||||
COMMAND CXX=${GCC_TOOL} CXXFLAGS="${GCC_CXXFLAGS}" ${CMAKE_COMMAND}
|
||||
-DCMAKE_BUILD_TYPE=Debug -GNinja
|
||||
-DJSON_BuildTests=ON -DJSON_MultipleHeader=OFF -DJSON_FastTests=ON
|
||||
-DJSON_BuildTests=ON -DJSON_MultipleHeaders=OFF -DJSON_FastTests=ON
|
||||
-S${PROJECT_SOURCE_DIR} -B${PROJECT_BINARY_DIR}/build_single_header
|
||||
COMMAND ${CMAKE_COMMAND} --build ${PROJECT_BINARY_DIR}/build_single_header
|
||||
COMMAND cd ${PROJECT_BINARY_DIR}/build_single_header && ${CMAKE_CTEST_COMMAND} --parallel ${N} --output-on-failure
|
||||
|
||||
@ -50,9 +50,10 @@ endforeach()
|
||||
# [COMPILE_FEATURES <args>...]
|
||||
# [COMPILE_OPTIONS <args>...]
|
||||
# [LINK_LIBRARIES <args>...]
|
||||
# [LINK_OPTIONS <args>...])
|
||||
# [LINK_OPTIONS <args>...]
|
||||
# [TEST_PROPERTIES <args>...])
|
||||
#
|
||||
# Supply test- and standard-specific build settings.
|
||||
# Supply test- and standard-specific build settings and/or test properties.
|
||||
# Specify multiple tests using a list e.g., "test-foo;test-bar".
|
||||
#
|
||||
# Must be called BEFORE the test is created.
|
||||
@ -60,7 +61,7 @@ endforeach()
|
||||
|
||||
function(json_test_set_test_options tests)
|
||||
cmake_parse_arguments(args "" ""
|
||||
"CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS"
|
||||
"CXX_STANDARDS;COMPILE_DEFINITIONS;COMPILE_FEATURES;COMPILE_OPTIONS;LINK_LIBRARIES;LINK_OPTIONS;TEST_PROPERTIES"
|
||||
${ARGN})
|
||||
|
||||
if(NOT args_CXX_STANDARDS)
|
||||
@ -91,10 +92,23 @@ function(json_test_set_test_options tests)
|
||||
target_compile_options(${test_interface} INTERFACE ${args_COMPILE_OPTIONS})
|
||||
target_link_libraries (${test_interface} INTERFACE ${args_LINK_LIBRARIES})
|
||||
target_link_options(${test_interface} INTERFACE ${args_LINK_OPTIONS})
|
||||
#set_target_properties(${test_interface} PROPERTIES JSON_TEST_PROPERTIES "${args_TEST_PROPERTIES}")
|
||||
set_property(DIRECTORY PROPERTY
|
||||
${test_interface}_TEST_PROPERTIES "${args_TEST_PROPERTIES}"
|
||||
)
|
||||
endforeach()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# for internal use by _json_test_add_test()
|
||||
function(_json_test_apply_test_properties test_target properties_target)
|
||||
#get_target_property(test_properties ${properties_target} JSON_TEST_PROPERTIES)
|
||||
get_property(test_properties DIRECTORY PROPERTY ${properties_target}_TEST_PROPERTIES)
|
||||
if(test_properties)
|
||||
set_tests_properties(${test_target} PROPERTIES ${test_properties})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# for internal use by json_test_add_test_for()
|
||||
function(_json_test_add_test test_name file main cxx_standard)
|
||||
set(test_target ${test_name}_cpp${cxx_standard})
|
||||
@ -142,6 +156,23 @@ function(_json_test_add_test test_name file main cxx_standard)
|
||||
endif()
|
||||
set_tests_properties(${test_target} PROPERTIES LABELS "all" FIXTURES_REQUIRED TEST_DATA)
|
||||
|
||||
# apply standard-specific test properties
|
||||
if(TARGET _json_test_interface__cpp_${cxx_standard})
|
||||
_json_test_apply_test_properties(${test_target} _json_test_interface__cpp_${cxx_standard})
|
||||
endif()
|
||||
|
||||
# apply test-specific test properties
|
||||
if(TARGET _json_test_interface_${test_name})
|
||||
_json_test_apply_test_properties(${test_target} _json_test_interface_${test_name})
|
||||
endif()
|
||||
|
||||
# apply test- and standard-specific test properties
|
||||
if(TARGET _json_test_interface_${test_name}_cpp_${cxx_standard})
|
||||
_json_test_apply_test_properties(${test_target}
|
||||
_json_test_interface_${test_name}_cpp_${cxx_standard}
|
||||
)
|
||||
endif()
|
||||
|
||||
if(JSON_Valgrind)
|
||||
add_test(NAME ${test_target}_valgrind
|
||||
COMMAND ${memcheck_command} $<TARGET_FILE:${test_target}> ${DOCTEST_TEST_FILTER}
|
||||
|
||||
@ -512,16 +512,23 @@ decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
|
||||
// see is_usable_as_basic_json_key_type below
|
||||
template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
ObjectKeyType>::value)
|
||||
&& (!RequireTransparentComparator
|
||||
|| is_detected <detect_is_transparent, Comparator>::value)
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
@ -530,17 +537,13 @@ using detect_is_transparent = typename T::is_transparent;
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
using is_usable_as_basic_json_key_type = typename std::conditional <
|
||||
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
|
||||
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
|
||||
RequireTransparentComparator, ExcludeObjectKeyType>::value
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
|
||||
@ -61,7 +61,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
void write_characters(const CharType* s, std::size_t length) override
|
||||
{
|
||||
std::copy(s, s + length, std::back_inserter(v));
|
||||
v.insert(v.end(), s, s + length);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@ -2001,7 +2001,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
reference at(KeyType && key)
|
||||
{
|
||||
// at only works for objects
|
||||
@ -2039,7 +2039,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_reference at(KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
@ -2169,7 +2169,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
reference operator[](KeyType && key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
@ -2193,7 +2193,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
const_reference operator[](KeyType && key) const
|
||||
{
|
||||
// const operator[] only works for objects
|
||||
@ -2262,7 +2262,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value
|
||||
&& detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
&& detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
@ -2561,7 +2561,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
return erase_internal(std::forward<KeyType>(key));
|
||||
@ -2628,7 +2628,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
auto result = end();
|
||||
@ -2644,7 +2644,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_iterator find(KeyType && key) const
|
||||
{
|
||||
auto result = cend();
|
||||
@ -2668,7 +2668,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
@ -2685,7 +2685,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
bool contains(KeyType && key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
|
||||
|
||||
@ -18,6 +18,7 @@
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/macro_scope.hpp>
|
||||
#include <nlohmann/detail/meta/type_traits.hpp>
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
@ -60,21 +61,50 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::emplace_back(key, t);
|
||||
return {--this->end(), true};
|
||||
Container::emplace_back(key, std::forward<T>(t));
|
||||
return {std::prev(this->end()), true};
|
||||
}
|
||||
|
||||
T& operator[](const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
std::pair<iterator, bool> emplace(KeyType && key, T && t)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
|
||||
return {std::prev(this->end()), true};
|
||||
}
|
||||
|
||||
T& operator[](const key_type& key)
|
||||
{
|
||||
return emplace(key, T{}).first->second;
|
||||
}
|
||||
|
||||
const T& operator[](const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
T & operator[](KeyType && key)
|
||||
{
|
||||
return emplace(std::forward<KeyType>(key), T{}).first->second;
|
||||
}
|
||||
|
||||
const T& operator[](const key_type& key) const
|
||||
{
|
||||
return at(key);
|
||||
}
|
||||
|
||||
T& at(const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
const T & operator[](KeyType && key) const
|
||||
{
|
||||
return at(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
T& at(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -87,7 +117,9 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
const T& at(const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
T & at(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -100,7 +132,56 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
size_type erase(const Key& key)
|
||||
const T& at(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
const T & at(KeyType && key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
{
|
||||
it->~value_type(); // Destroy but keep allocation
|
||||
new (&*it) value_type{std::move(*next)};
|
||||
}
|
||||
Container::pop_back();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -126,6 +207,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
|
||||
iterator erase(iterator first, iterator last)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
const auto elements_affected = std::distance(first, last);
|
||||
const auto offset = std::distance(Container::begin(), first);
|
||||
|
||||
@ -172,7 +258,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return Container::begin() + offset;
|
||||
}
|
||||
|
||||
size_type count(const Key& key) const
|
||||
size_type count(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -184,7 +270,21 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator find(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -196,7 +296,21 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
|
||||
@ -3800,16 +3800,23 @@ decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
|
||||
decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
|
||||
>> : std::true_type {};
|
||||
|
||||
// checks if BasicJsonType::object_t::key_type and KeyType are comparable using Compare functor
|
||||
template<typename BasicJsonType, typename KeyType>
|
||||
using is_key_type_comparable = typename is_comparable <
|
||||
typename BasicJsonType::object_comparator_t,
|
||||
const key_type_t<typename BasicJsonType::object_t>&,
|
||||
KeyType >::type;
|
||||
|
||||
template<typename T>
|
||||
using detect_is_transparent = typename T::is_transparent;
|
||||
|
||||
// type trait to check if KeyType can be used as object key (without a BasicJsonType)
|
||||
// see is_usable_as_basic_json_key_type below
|
||||
template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
ObjectKeyType>::value)
|
||||
&& (!RequireTransparentComparator
|
||||
|| is_detected <detect_is_transparent, Comparator>::value)
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
// type trait to check if KeyType can be used as object key
|
||||
// true if:
|
||||
// - KeyType is comparable with BasicJsonType::object_t::key_type
|
||||
@ -3818,17 +3825,13 @@ using detect_is_transparent = typename T::is_transparent;
|
||||
// - KeyType is not a JSON iterator or json_pointer
|
||||
template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
|
||||
bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
|
||||
using is_usable_as_key_type = typename std::conditional <
|
||||
is_key_type_comparable<BasicJsonType, KeyTypeCVRef>::value
|
||||
&& !(ExcludeObjectKeyType && std::is_same<KeyType,
|
||||
typename BasicJsonType::object_t::key_type>::value)
|
||||
&& (!RequireTransparentComparator || is_detected <
|
||||
detect_is_transparent,
|
||||
typename BasicJsonType::object_comparator_t >::value)
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value
|
||||
&& !is_json_pointer<KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
using is_usable_as_basic_json_key_type = typename std::conditional <
|
||||
is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
|
||||
typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
|
||||
RequireTransparentComparator, ExcludeObjectKeyType>::value
|
||||
&& !is_json_iterator_of<BasicJsonType, KeyType>::value,
|
||||
std::true_type,
|
||||
std::false_type >::type;
|
||||
|
||||
template<typename ObjectType, typename KeyType>
|
||||
using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
|
||||
@ -14508,7 +14511,7 @@ class output_vector_adapter : public output_adapter_protocol<CharType>
|
||||
JSON_HEDLEY_NON_NULL(2)
|
||||
void write_characters(const CharType* s, std::size_t length) override
|
||||
{
|
||||
std::copy(s, s + length, std::back_inserter(v));
|
||||
v.insert(v.end(), s, s + length);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -18552,6 +18555,8 @@ class serializer
|
||||
|
||||
// #include <nlohmann/detail/macro_scope.hpp>
|
||||
|
||||
// #include <nlohmann/detail/meta/type_traits.hpp>
|
||||
|
||||
|
||||
namespace nlohmann
|
||||
{
|
||||
@ -18594,21 +18599,50 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::emplace_back(key, t);
|
||||
return {--this->end(), true};
|
||||
Container::emplace_back(key, std::forward<T>(t));
|
||||
return {std::prev(this->end()), true};
|
||||
}
|
||||
|
||||
T& operator[](const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
std::pair<iterator, bool> emplace(KeyType && key, T && t)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return {it, false};
|
||||
}
|
||||
}
|
||||
Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
|
||||
return {std::prev(this->end()), true};
|
||||
}
|
||||
|
||||
T& operator[](const key_type& key)
|
||||
{
|
||||
return emplace(key, T{}).first->second;
|
||||
}
|
||||
|
||||
const T& operator[](const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
T & operator[](KeyType && key)
|
||||
{
|
||||
return emplace(std::forward<KeyType>(key), T{}).first->second;
|
||||
}
|
||||
|
||||
const T& operator[](const key_type& key) const
|
||||
{
|
||||
return at(key);
|
||||
}
|
||||
|
||||
T& at(const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
const T & operator[](KeyType && key) const
|
||||
{
|
||||
return at(std::forward<KeyType>(key));
|
||||
}
|
||||
|
||||
T& at(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -18621,7 +18655,9 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
const T& at(const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
T & at(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -18634,7 +18670,56 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
size_type erase(const Key& key)
|
||||
const T& at(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
const T & at(KeyType && key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it->second;
|
||||
}
|
||||
}
|
||||
|
||||
JSON_THROW(std::out_of_range("key not found"));
|
||||
}
|
||||
|
||||
size_type erase(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
// Since we cannot move const Keys, re-construct them in place
|
||||
for (auto next = it; ++next != this->end(); ++it)
|
||||
{
|
||||
it->~value_type(); // Destroy but keep allocation
|
||||
new (&*it) value_type{std::move(*next)};
|
||||
}
|
||||
Container::pop_back();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -18660,6 +18745,11 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
|
||||
iterator erase(iterator first, iterator last)
|
||||
{
|
||||
if (first == last)
|
||||
{
|
||||
return first;
|
||||
}
|
||||
|
||||
const auto elements_affected = std::distance(first, last);
|
||||
const auto offset = std::distance(Container::begin(), first);
|
||||
|
||||
@ -18706,7 +18796,7 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return Container::begin() + offset;
|
||||
}
|
||||
|
||||
size_type count(const Key& key) const
|
||||
size_type count(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -18718,7 +18808,21 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator find(const Key& key)
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
iterator find(const key_type& key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -18730,7 +18834,21 @@ template <class Key, class T, class IgnoredLess = std::less<Key>,
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
const_iterator find(const Key& key) const
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
if (m_compare(it->first, key))
|
||||
{
|
||||
return it;
|
||||
}
|
||||
}
|
||||
return Container::end();
|
||||
}
|
||||
|
||||
const_iterator find(const key_type& key) const
|
||||
{
|
||||
for (auto it = this->begin(); it != this->end(); ++it)
|
||||
{
|
||||
@ -20708,7 +20826,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
reference at(KeyType && key)
|
||||
{
|
||||
// at only works for objects
|
||||
@ -20746,7 +20864,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element with bounds checking
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/at/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_reference at(KeyType && key) const
|
||||
{
|
||||
// at only works for objects
|
||||
@ -20876,7 +20994,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
reference operator[](KeyType && key)
|
||||
{
|
||||
// implicitly convert null value to an empty object
|
||||
@ -20900,7 +21018,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief access specified object element
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
const_reference operator[](KeyType && key) const
|
||||
{
|
||||
// const operator[] only works for objects
|
||||
@ -20969,7 +21087,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
template < class KeyType, class ValueType, detail::enable_if_t <
|
||||
detail::is_getable<basic_json_t, ValueType>::value
|
||||
&& !std::is_same<value_t, ValueType>::value
|
||||
&& detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
&& detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
|
||||
typename std::decay<ValueType>::type value(KeyType && key, ValueType && default_value) const
|
||||
{
|
||||
// value only works for objects
|
||||
@ -21268,7 +21386,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief remove element from a JSON object given a key
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/erase/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type erase(KeyType && key)
|
||||
{
|
||||
return erase_internal(std::forward<KeyType>(key));
|
||||
@ -21335,7 +21453,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
iterator find(KeyType && key)
|
||||
{
|
||||
auto result = end();
|
||||
@ -21351,7 +21469,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief find an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/find/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
const_iterator find(KeyType && key) const
|
||||
{
|
||||
auto result = cend();
|
||||
@ -21375,7 +21493,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief returns the number of occurrences of a key in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/count/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
size_type count(KeyType && key) const
|
||||
{
|
||||
// return 0 for all nonobject types
|
||||
@ -21392,7 +21510,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @brief check the existence of an element in a JSON object
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/contains/
|
||||
template<class KeyType, detail::enable_if_t<
|
||||
detail::is_usable_as_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
|
||||
bool contains(KeyType && key) const
|
||||
{
|
||||
return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
|
||||
|
||||
@ -80,12 +80,17 @@ endif()
|
||||
# disable exceptions for test-disabled_exceptions
|
||||
json_test_set_test_options(test-disabled_exceptions COMPILE_DEFINITIONS JSON_NOEXCEPTION)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
json_test_set_test_options(test-disabled_exceptions COMPILE_OPTIONS -fno-exceptions)
|
||||
json_test_set_test_options(test-disabled_exceptions COMPILE_OPTIONS -fno-exceptions)
|
||||
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
|
||||
# disabled due to https://github.com/nlohmann/json/discussions/2824
|
||||
#json_test_set_test_options(test-disabled_exceptions COMPILE_DEFINITIONS _HAS_EXCEPTIONS=0 COMPILE_OPTIONS /EH)
|
||||
endif()
|
||||
|
||||
# set timeouts for Unicode tests
|
||||
json_test_set_test_options("test-unicode2;test-unicode3;test-unicode4;test-unicode5"
|
||||
TEST_PROPERTIES "TIMEOUT_AFTER_MATCH;1500$<SEMICOLON>UTF-8 strings checked"
|
||||
)
|
||||
|
||||
#############################################################################
|
||||
# add unit tests
|
||||
#############################################################################
|
||||
|
||||
@ -9,6 +9,8 @@
|
||||
#include <benchmark/benchmark.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
#include <test_data.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
@ -115,4 +117,63 @@ BENCHMARK_CAPTURE(Dump, small_signed_ints / -, TEST_DATA_DIRECTORY "/regression/
|
||||
BENCHMARK_CAPTURE(Dump, small_signed_ints / 4, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json", 4);
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// serialize CBOR
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static void ToCbor(benchmark::State& state, const char* filename)
|
||||
{
|
||||
std::ifstream f(filename);
|
||||
std::string str((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
|
||||
json j = json::parse(str);
|
||||
|
||||
while (state.KeepRunning())
|
||||
{
|
||||
json::to_cbor(j);
|
||||
}
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
|
||||
}
|
||||
BENCHMARK_CAPTURE(ToCbor, jeopardy, TEST_DATA_DIRECTORY "/jeopardy/jeopardy.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, canada, TEST_DATA_DIRECTORY "/nativejson-benchmark/canada.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, citm_catalog, TEST_DATA_DIRECTORY "/nativejson-benchmark/citm_catalog.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, twitter, TEST_DATA_DIRECTORY "/nativejson-benchmark/twitter.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, floats, TEST_DATA_DIRECTORY "/regression/floats.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, signed_ints, TEST_DATA_DIRECTORY "/regression/signed_ints.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, unsigned_ints, TEST_DATA_DIRECTORY "/regression/unsigned_ints.json");
|
||||
BENCHMARK_CAPTURE(ToCbor, small_signed_ints, TEST_DATA_DIRECTORY "/regression/small_signed_ints.json");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// serialize binary CBOR
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
static void BinaryToCbor(benchmark::State& state)
|
||||
{
|
||||
std::vector<uint8_t> data(256);
|
||||
std::iota(data.begin(), data.end(), 0);
|
||||
|
||||
auto it = data.begin();
|
||||
std::vector<uint8_t> in;
|
||||
in.reserve(state.range(0));
|
||||
for (int i = 0; i < state.range(0); ++i)
|
||||
{
|
||||
if (it == data.end())
|
||||
{
|
||||
it = data.begin();
|
||||
}
|
||||
|
||||
in.push_back(*it);
|
||||
++it;
|
||||
}
|
||||
|
||||
json::binary_t bin{in};
|
||||
json j{{"type", "binary"}, {"data", bin}};
|
||||
|
||||
while (state.KeepRunning())
|
||||
{
|
||||
json::to_cbor(j);
|
||||
}
|
||||
|
||||
state.SetBytesProcessed(state.iterations() * json::to_cbor(j).size());
|
||||
}
|
||||
BENCHMARK(BinaryToCbor)->RangeMultiplier(2)->Range(8, 8 << 12);
|
||||
|
||||
BENCHMARK_MAIN();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -13,7 +13,9 @@ using nlohmann::json;
|
||||
|
||||
// This test suite uses range for loops where values are copied. This is inefficient in usual code, but required to achieve 100% coverage.
|
||||
DOCTEST_GCC_SUPPRESS_WARNING_PUSH
|
||||
DOCTEST_GCC_SUPPRESS_WARNING("-Wrange-loop-construct")
|
||||
#if DOCTEST_GCC >= DOCTEST_COMPILER(11, 0, 0)
|
||||
DOCTEST_GCC_SUPPRESS_WARNING("-Wrange-loop-construct")
|
||||
#endif
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING_PUSH
|
||||
DOCTEST_CLANG_SUPPRESS_WARNING("-Wrange-loop-construct")
|
||||
|
||||
|
||||
@ -895,7 +895,7 @@ TEST_CASE("iterators 2")
|
||||
}
|
||||
|
||||
// libstdc++ algorithms don't work with Clang 15 (04/2022)
|
||||
#if !defined(__clang__) || (defined(__clang__) && defined(__GLIBCXX__))
|
||||
#if !DOCTEST_CLANG || (DOCTEST_CLANG && defined(__GLIBCXX__))
|
||||
SECTION("algorithms")
|
||||
{
|
||||
SECTION("copy")
|
||||
@ -934,7 +934,7 @@ TEST_CASE("iterators 2")
|
||||
|
||||
// libstdc++ views don't work with Clang 15 (04/2022)
|
||||
// libc++ hides limited ranges implementation behind guard macro
|
||||
#if !(defined(__clang__) && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
|
||||
#if !(DOCTEST_CLANG && (defined(__GLIBCXX__) || defined(_LIBCPP_HAS_NO_INCOMPLETE_RANGES)))
|
||||
SECTION("views")
|
||||
{
|
||||
SECTION("reverse")
|
||||
|
||||
@ -1499,7 +1499,7 @@ TEST_CASE("regression tests, exceptions dependent")
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// the code below fails with Clang on Windows, so we need to exclude it there
|
||||
#if defined(__clang__) && (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__))
|
||||
#if DOCTEST_CLANG && (defined(WIN32) || defined(_WIN32) || defined(__WIN32) && !defined(__CYGWIN__))
|
||||
#else
|
||||
template <typename T> class array {};
|
||||
template <typename T> class object {};
|
||||
|
||||
@ -782,7 +782,7 @@ TEST_CASE("regression tests 2")
|
||||
const auto j_path = j.get<nlohmann::detail::std_fs::path>();
|
||||
CHECK(j_path == text_path);
|
||||
|
||||
#if defined(__clang__) || ((defined(__GNUC__) && !defined(__INTEL_COMPILER)) && (__GNUC__ > 8 || (__GNUC__ == 8 && __GNUC_MINOR__ >= 4)))
|
||||
#if DOCTEST_CLANG || DOCTEST_GCC >= DOCTEST_COMPILER(8, 4, 0)
|
||||
// only known to work on Clang and GCC >=8.4
|
||||
CHECK_THROWS_WITH_AS(nlohmann::detail::std_fs::path(json(1)), "[json.exception.type_error.302] type must be string, but is number", json::type_error);
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user