mirror of
https://github.com/nlohmann/json.git
synced 2024-08-23 05:22:28 +02:00
Merge branch 'develop' of https://github.com/nlohmann/json into develop
This commit is contained in:
commit
3d67ec40a6
110
CMakeLists.txt
110
CMakeLists.txt
|
@ -1,56 +1,78 @@
|
||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0.0)
|
||||||
|
|
||||||
# define the project
|
##
|
||||||
project(nlohmann_json VERSION 2.1.1 LANGUAGES CXX)
|
## PROJECT
|
||||||
|
## name and version
|
||||||
|
##
|
||||||
|
project(nlohmann_json VERSION 2.1.1)
|
||||||
|
|
||||||
|
##
|
||||||
|
## OPTIONS
|
||||||
|
##
|
||||||
option(JSON_BuildTests "Build the unit tests" ON)
|
option(JSON_BuildTests "Build the unit tests" ON)
|
||||||
|
|
||||||
# define project variables
|
##
|
||||||
set(JSON_TARGET_NAME ${PROJECT_NAME})
|
## CONFIGURATION
|
||||||
set(JSON_PACKAGE_NAME ${JSON_TARGET_NAME})
|
##
|
||||||
set(JSON_TARGETS_FILENAME "${JSON_PACKAGE_NAME}Targets.cmake")
|
set(NLOHMANN_JSON_TARGET_NAME ${PROJECT_NAME})
|
||||||
set(JSON_CONFIG_FILENAME "${JSON_PACKAGE_NAME}Config.cmake")
|
set(NLOHMANN_JSON_SOURCE_DIR "src/")
|
||||||
set(JSON_CONFIGVERSION_FILENAME "${JSON_PACKAGE_NAME}ConfigVersion.cmake")
|
set(NLOHMANN_JSON_CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
|
||||||
set(JSON_CONFIG_DESTINATION "cmake")
|
set(NLOHMANN_JSON_INCLUDE_INSTALL_DIR "include")
|
||||||
set(JSON_INCLUDE_DESTINATION "include/nlohmann")
|
set(NLOHMANN_JSON_HEADER_INSTALL_DIR "${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}/nlohmann")
|
||||||
|
set(NLOHMANN_JSON_TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
|
||||||
|
set(NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE "cmake/config.cmake.in")
|
||||||
|
set(NLOHMANN_JSON_CMAKE_CONFIG_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake_config")
|
||||||
|
set(NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
|
||||||
|
set(NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE "${NLOHMANN_JSON_CMAKE_CONFIG_DIR}/${PROJECT_NAME}Config.cmake")
|
||||||
|
|
||||||
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
##
|
||||||
|
## TARGET
|
||||||
|
## create target and add include path
|
||||||
|
##
|
||||||
|
add_library(${NLOHMANN_JSON_TARGET_NAME} INTERFACE)
|
||||||
|
|
||||||
# create and configure the library target
|
target_include_directories(
|
||||||
add_library(${JSON_TARGET_NAME} INTERFACE)
|
${NLOHMANN_JSON_TARGET_NAME}
|
||||||
target_include_directories(${JSON_TARGET_NAME} INTERFACE
|
INTERFACE $<INSTALL_INTERFACE:include/>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/src>
|
)
|
||||||
$<INSTALL_INTERFACE:${JSON_INCLUDE_DESTINATION}>)
|
|
||||||
|
##
|
||||||
# create and configure the unit test target
|
## TESTS
|
||||||
|
## create and configure the unit test target
|
||||||
|
##
|
||||||
if(JSON_BuildTests)
|
if(JSON_BuildTests)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
|
include_directories(${NLOHMANN_JSON_SOURCE_DIR})
|
||||||
add_subdirectory(test)
|
add_subdirectory(test)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# generate a config and config version file for the package
|
##
|
||||||
|
## INSTALL
|
||||||
|
## install header files, generate and install cmake config files for find_package()
|
||||||
|
##
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
configure_package_config_file("cmake/config.cmake.in"
|
write_basic_package_version_file(
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}"
|
${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE} COMPATIBILITY SameMajorVersion
|
||||||
INSTALL_DESTINATION ${JSON_CONFIG_DESTINATION}
|
)
|
||||||
PATH_VARS JSON_INCLUDE_DESTINATION)
|
configure_package_config_file(
|
||||||
write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}"
|
${NLOHMANN_JSON_CMAKE_CONFIG_TEMPLATE}
|
||||||
VERSION ${PROJECT_VERSION}
|
${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE}
|
||||||
COMPATIBILITY SameMajorVersion)
|
INSTALL_DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||||
|
)
|
||||||
# export the library target and store build directory in package registry
|
install(
|
||||||
export(TARGETS ${JSON_TARGET_NAME}
|
DIRECTORY ${NLOHMANN_JSON_SOURCE_DIR}
|
||||||
FILE "${CMAKE_CURRENT_BINARY_DIR}/${JSON_TARGETS_FILENAME}")
|
DESTINATION ${NLOHMANN_JSON_HEADER_INSTALL_DIR}
|
||||||
export(PACKAGE ${JSON_PACKAGE_NAME})
|
)
|
||||||
|
install(
|
||||||
# install library target and config files
|
FILES ${NLOHMANN_JSON_CMAKE_PROJECT_CONFIG_FILE} ${NLOHMANN_JSON_CMAKE_VERSION_CONFIG_FILE}
|
||||||
install(TARGETS ${JSON_TARGET_NAME}
|
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||||
EXPORT ${JSON_PACKAGE_NAME})
|
)
|
||||||
install(FILES "src/json.hpp"
|
install(
|
||||||
DESTINATION ${JSON_INCLUDE_DESTINATION})
|
TARGETS ${NLOHMANN_JSON_TARGET_NAME}
|
||||||
install(EXPORT ${JSON_PACKAGE_NAME}
|
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||||
FILE ${JSON_TARGETS_FILENAME}
|
INCLUDES DESTINATION ${NLOHMANN_JSON_INCLUDE_INSTALL_DIR}
|
||||||
DESTINATION ${JSON_CONFIG_DESTINATION})
|
)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIG_FILENAME}"
|
install(
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/${JSON_CONFIGVERSION_FILENAME}"
|
EXPORT ${NLOHMANN_JSON_TARGETS_EXPORT_NAME}
|
||||||
DESTINATION ${JSON_CONFIG_DESTINATION})
|
DESTINATION ${NLOHMANN_JSON_CONFIG_INSTALL_DIR}
|
||||||
|
)
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
@PACKAGE_INIT@
|
@PACKAGE_INIT@
|
||||||
set_and_check(JSON_INCLUDE_DIR "@PACKAGE_JSON_INCLUDE_DESTINATION@")
|
include("${CMAKE_CURRENT_LIST_DIR}/@NLOHMANN_JSON_TARGETS_EXPORT_NAME@.cmake")
|
||||||
|
check_required_components("@PROJECT_NAME@")
|
||||||
cmake_policy(PUSH)
|
|
||||||
cmake_policy(SET CMP0024 OLD)
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/@JSON_TARGETS_FILENAME@)
|
|
||||||
cmake_policy(POP)
|
|
||||||
|
|
201
src/json.hpp
201
src/json.hpp
|
@ -575,6 +575,14 @@ struct external_constructor<value_t::string>
|
||||||
j.m_value = s;
|
j.m_value = s;
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
||||||
|
{
|
||||||
|
j.m_type = value_t::string;
|
||||||
|
j.m_value = std::move(s);
|
||||||
|
j.assert_invariant();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
|
@ -624,6 +632,14 @@ struct external_constructor<value_t::array>
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||||
|
{
|
||||||
|
j.m_type = value_t::array;
|
||||||
|
j.m_value = std::move(arr);
|
||||||
|
j.assert_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleArrayType,
|
template<typename BasicJsonType, typename CompatibleArrayType,
|
||||||
enable_if_t<not std::is_same<CompatibleArrayType,
|
enable_if_t<not std::is_same<CompatibleArrayType,
|
||||||
typename BasicJsonType::array_t>::value,
|
typename BasicJsonType::array_t>::value,
|
||||||
|
@ -662,6 +678,14 @@ struct external_constructor<value_t::object>
|
||||||
j.assert_invariant();
|
j.assert_invariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||||
|
{
|
||||||
|
j.m_type = value_t::object;
|
||||||
|
j.m_value = std::move(obj);
|
||||||
|
j.assert_invariant();
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename CompatibleObjectType,
|
template<typename BasicJsonType, typename CompatibleObjectType,
|
||||||
enable_if_t<not std::is_same<CompatibleObjectType,
|
enable_if_t<not std::is_same<CompatibleObjectType,
|
||||||
typename BasicJsonType::object_t>::value, int> = 0>
|
typename BasicJsonType::object_t>::value, int> = 0>
|
||||||
|
@ -850,6 +874,12 @@ void to_json(BasicJsonType& j, const CompatibleString& s)
|
||||||
external_constructor<value_t::string>::construct(j, s);
|
external_constructor<value_t::string>::construct(j, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType>
|
||||||
|
void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
|
||||||
|
{
|
||||||
|
external_constructor<value_t::string>::construct(j, std::move(s));
|
||||||
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename FloatType,
|
template<typename BasicJsonType, typename FloatType,
|
||||||
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
|
enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
|
||||||
void to_json(BasicJsonType& j, FloatType val) noexcept
|
void to_json(BasicJsonType& j, FloatType val) noexcept
|
||||||
|
@ -900,13 +930,25 @@ void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
|
||||||
external_constructor<value_t::array>::construct(j, arr);
|
external_constructor<value_t::array>::construct(j, arr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType>
|
||||||
|
void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
|
||||||
|
{
|
||||||
|
external_constructor<value_t::array>::construct(j, std::move(arr));
|
||||||
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
typename BasicJsonType, typename CompatibleObjectType,
|
typename BasicJsonType, typename CompatibleObjectType,
|
||||||
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
|
enable_if_t<is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value,
|
||||||
int> = 0 >
|
int> = 0 >
|
||||||
void to_json(BasicJsonType& j, const CompatibleObjectType& arr)
|
void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
|
||||||
{
|
{
|
||||||
external_constructor<value_t::object>::construct(j, arr);
|
external_constructor<value_t::object>::construct(j, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename BasicJsonType>
|
||||||
|
void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
|
||||||
|
{
|
||||||
|
external_constructor<value_t::object>::construct(j, std::move(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename BasicJsonType, typename T, std::size_t N,
|
template<typename BasicJsonType, typename T, std::size_t N,
|
||||||
|
@ -6799,6 +6841,67 @@ class serializer
|
||||||
/// the indentation string
|
/// the indentation string
|
||||||
string_t indent_string;
|
string_t indent_string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename BasicJsonType>
|
||||||
|
struct json_ref
|
||||||
|
{
|
||||||
|
typedef BasicJsonType value_type;
|
||||||
|
|
||||||
|
json_ref(value_type&& value)
|
||||||
|
: owned_value_(std::move(value))
|
||||||
|
, is_rvalue_(true)
|
||||||
|
{
|
||||||
|
value_ref_ = &owned_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_ref(const value_type& value)
|
||||||
|
: value_ref_(const_cast<value_type*>(&value))
|
||||||
|
, is_rvalue_(false)
|
||||||
|
{}
|
||||||
|
|
||||||
|
json_ref(std::initializer_list<json_ref> init)
|
||||||
|
: owned_value_(init)
|
||||||
|
, is_rvalue_(true)
|
||||||
|
{
|
||||||
|
value_ref_ = &owned_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class... Args>
|
||||||
|
json_ref(Args... args)
|
||||||
|
: owned_value_(std::forward<Args>(args)...)
|
||||||
|
, is_rvalue_(true)
|
||||||
|
{
|
||||||
|
value_ref_ = &owned_value_;
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type moved_or_copied() const
|
||||||
|
{
|
||||||
|
if (is_rvalue_)
|
||||||
|
{
|
||||||
|
return std::move(*value_ref_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return *value_ref_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type const& operator*() const
|
||||||
|
{
|
||||||
|
return *static_cast<value_type const*>(value_ref_);
|
||||||
|
}
|
||||||
|
|
||||||
|
value_type const* operator->() const
|
||||||
|
{
|
||||||
|
return static_cast<value_type const*>(value_ref_);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
value_type * value_ref_;
|
||||||
|
mutable value_type owned_value_;
|
||||||
|
bool is_rvalue_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
/// namespace to hold default `to_json` / `from_json` functions
|
/// namespace to hold default `to_json` / `from_json` functions
|
||||||
|
@ -7297,6 +7400,7 @@ class basic_json
|
||||||
template<typename T, typename SFINAE>
|
template<typename T, typename SFINAE>
|
||||||
using json_serializer = JSONSerializer<T, SFINAE>;
|
using json_serializer = JSONSerializer<T, SFINAE>;
|
||||||
|
|
||||||
|
using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
|
||||||
|
|
||||||
////////////////
|
////////////////
|
||||||
// exceptions //
|
// exceptions //
|
||||||
|
@ -8025,18 +8129,36 @@ class basic_json
|
||||||
string = create<string_t>(value);
|
string = create<string_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// constructor for rvalue strings
|
||||||
|
json_value(string_t&& value)
|
||||||
|
{
|
||||||
|
string = create<string_t>(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
/// constructor for objects
|
/// constructor for objects
|
||||||
json_value(const object_t& value)
|
json_value(const object_t& value)
|
||||||
{
|
{
|
||||||
object = create<object_t>(value);
|
object = create<object_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// constructor for rvalue objects
|
||||||
|
json_value(object_t&& value)
|
||||||
|
{
|
||||||
|
object = create<object_t>(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
/// constructor for arrays
|
/// constructor for arrays
|
||||||
json_value(const array_t& value)
|
json_value(const array_t& value)
|
||||||
{
|
{
|
||||||
array = create<array_t>(value);
|
array = create<array_t>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// constructor for rvalue arrays
|
||||||
|
json_value(array_t&& value)
|
||||||
|
{
|
||||||
|
array = create<array_t>(std::move(value));
|
||||||
|
}
|
||||||
|
|
||||||
void destroy(value_t t)
|
void destroy(value_t t)
|
||||||
{
|
{
|
||||||
switch (t)
|
switch (t)
|
||||||
|
@ -8310,10 +8432,10 @@ class basic_json
|
||||||
With the rules described above, the following JSON values cannot be
|
With the rules described above, the following JSON values cannot be
|
||||||
expressed by an initializer list:
|
expressed by an initializer list:
|
||||||
|
|
||||||
- the empty array (`[]`): use @ref array(std::initializer_list<basic_json>)
|
- the empty array (`[]`): use @ref array(initializer_list_t)
|
||||||
with an empty initializer list in this case
|
with an empty initializer list in this case
|
||||||
- arrays whose elements satisfy rule 2: use @ref
|
- arrays whose elements satisfy rule 2: use @ref
|
||||||
array(std::initializer_list<basic_json>) with the same initializer list
|
array(initializer_list_t) with the same initializer list
|
||||||
in this case
|
in this case
|
||||||
|
|
||||||
@note When used without parentheses around an empty initializer list, @ref
|
@note When used without parentheses around an empty initializer list, @ref
|
||||||
|
@ -8325,8 +8447,8 @@ class basic_json
|
||||||
@param[in] type_deduction internal parameter; when set to `true`, the type
|
@param[in] type_deduction internal parameter; when set to `true`, the type
|
||||||
of the JSON value is deducted from the initializer list @a init; when set
|
of the JSON value is deducted from the initializer list @a init; when set
|
||||||
to `false`, the type provided via @a manual_type is forced. This mode is
|
to `false`, the type provided via @a manual_type is forced. This mode is
|
||||||
used by the functions @ref array(std::initializer_list<basic_json>) and
|
used by the functions @ref array(initializer_list_t) and
|
||||||
@ref object(std::initializer_list<basic_json>).
|
@ref object(initializer_list_t).
|
||||||
|
|
||||||
@param[in] manual_type internal parameter; when @a type_deduction is set
|
@param[in] manual_type internal parameter; when @a type_deduction is set
|
||||||
to `false`, the created JSON value will use the provided type (only @ref
|
to `false`, the created JSON value will use the provided type (only @ref
|
||||||
|
@ -8337,7 +8459,7 @@ class basic_json
|
||||||
`value_t::object`, but @a init contains an element which is not a pair
|
`value_t::object`, but @a init contains an element which is not a pair
|
||||||
whose first element is a string. In this case, the constructor could not
|
whose first element is a string. In this case, the constructor could not
|
||||||
create an object. If @a type_deduction would have be `true`, an array
|
create an object. If @a type_deduction would have be `true`, an array
|
||||||
would have been created. See @ref object(std::initializer_list<basic_json>)
|
would have been created. See @ref object(initializer_list_t)
|
||||||
for an example.
|
for an example.
|
||||||
|
|
||||||
@complexity Linear in the size of the initializer list @a init.
|
@complexity Linear in the size of the initializer list @a init.
|
||||||
|
@ -8345,23 +8467,23 @@ class basic_json
|
||||||
@liveexample{The example below shows how JSON values are created from
|
@liveexample{The example below shows how JSON values are created from
|
||||||
initializer lists.,basic_json__list_init_t}
|
initializer lists.,basic_json__list_init_t}
|
||||||
|
|
||||||
@sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
|
@sa @ref array(initializer_list_t) -- create a JSON array
|
||||||
value from an initializer list
|
value from an initializer list
|
||||||
@sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
|
@sa @ref object(initializer_list_t) -- create a JSON object
|
||||||
value from an initializer list
|
value from an initializer list
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
basic_json(std::initializer_list<basic_json> init,
|
basic_json(initializer_list_t init,
|
||||||
bool type_deduction = true,
|
bool type_deduction = true,
|
||||||
value_t manual_type = value_t::array)
|
value_t manual_type = value_t::array)
|
||||||
{
|
{
|
||||||
// check if each element is an array with two elements whose first
|
// check if each element is an array with two elements whose first
|
||||||
// element is a string
|
// element is a string
|
||||||
bool is_an_object = std::all_of(init.begin(), init.end(),
|
bool is_an_object = std::all_of(init.begin(), init.end(),
|
||||||
[](const basic_json & element)
|
[](const detail::json_ref<basic_json>& element_ref)
|
||||||
{
|
{
|
||||||
return (element.is_array() and element.size() == 2 and element[0].is_string());
|
return (element_ref->is_array() and element_ref->size() == 2 and (*element_ref)[0].is_string());
|
||||||
});
|
});
|
||||||
|
|
||||||
// adjust type if type deduction is not wanted
|
// adjust type if type deduction is not wanted
|
||||||
|
@ -8386,16 +8508,19 @@ class basic_json
|
||||||
m_type = value_t::object;
|
m_type = value_t::object;
|
||||||
m_value = value_t::object;
|
m_value = value_t::object;
|
||||||
|
|
||||||
std::for_each(init.begin(), init.end(), [this](const basic_json & element)
|
std::for_each(init.begin(), init.end(), [this](const detail::json_ref<basic_json>& element_ref)
|
||||||
{
|
{
|
||||||
m_value.object->emplace(*(element[0].m_value.string), element[1]);
|
basic_json element = element_ref.moved_or_copied();
|
||||||
|
m_value.object->emplace(
|
||||||
|
std::move(*((*element.m_value.array)[0].m_value.string)),
|
||||||
|
std::move((*element.m_value.array)[1]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// the initializer list describes an array -> create array
|
// the initializer list describes an array -> create array
|
||||||
m_type = value_t::array;
|
m_type = value_t::array;
|
||||||
m_value.array = create<array_t>(init);
|
m_value.array = create<array_t>(init.begin(), init.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_invariant();
|
assert_invariant();
|
||||||
|
@ -8410,7 +8535,7 @@ class basic_json
|
||||||
|
|
||||||
@note This function is only needed to express two edge cases that cannot
|
@note This function is only needed to express two edge cases that cannot
|
||||||
be realized with the initializer list constructor (@ref
|
be realized with the initializer list constructor (@ref
|
||||||
basic_json(std::initializer_list<basic_json>, bool, value_t)). These cases
|
basic_json(initializer_list_t, bool, value_t)). These cases
|
||||||
are:
|
are:
|
||||||
1. creating an array whose elements are all pairs whose first element is a
|
1. creating an array whose elements are all pairs whose first element is a
|
||||||
string -- in this case, the initializer list constructor would create an
|
string -- in this case, the initializer list constructor would create an
|
||||||
|
@ -8428,15 +8553,14 @@ class basic_json
|
||||||
@liveexample{The following code shows an example for the `array`
|
@liveexample{The following code shows an example for the `array`
|
||||||
function.,array}
|
function.,array}
|
||||||
|
|
||||||
@sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
|
@sa @ref basic_json(initializer_list_t, bool, value_t) --
|
||||||
create a JSON value from an initializer list
|
create a JSON value from an initializer list
|
||||||
@sa @ref object(std::initializer_list<basic_json>) -- create a JSON object
|
@sa @ref object(initializer_list_t) -- create a JSON object
|
||||||
value from an initializer list
|
value from an initializer list
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
static basic_json array(std::initializer_list<basic_json> init =
|
static basic_json array(initializer_list_t init = {})
|
||||||
std::initializer_list<basic_json>())
|
|
||||||
{
|
{
|
||||||
return basic_json(init, false, value_t::array);
|
return basic_json(init, false, value_t::array);
|
||||||
}
|
}
|
||||||
|
@ -8449,10 +8573,10 @@ class basic_json
|
||||||
the initializer list is empty, the empty object `{}` is created.
|
the initializer list is empty, the empty object `{}` is created.
|
||||||
|
|
||||||
@note This function is only added for symmetry reasons. In contrast to the
|
@note This function is only added for symmetry reasons. In contrast to the
|
||||||
related function @ref array(std::initializer_list<basic_json>), there are
|
related function @ref array(initializer_list_t), there are
|
||||||
no cases which can only be expressed by this function. That is, any
|
no cases which can only be expressed by this function. That is, any
|
||||||
initializer list @a init can also be passed to the initializer list
|
initializer list @a init can also be passed to the initializer list
|
||||||
constructor @ref basic_json(std::initializer_list<basic_json>, bool, value_t).
|
constructor @ref basic_json(initializer_list_t, bool, value_t).
|
||||||
|
|
||||||
@param[in] init initializer list to create an object from (optional)
|
@param[in] init initializer list to create an object from (optional)
|
||||||
|
|
||||||
|
@ -8460,7 +8584,7 @@ class basic_json
|
||||||
|
|
||||||
@throw type_error.301 if @a init is not a list of pairs whose first
|
@throw type_error.301 if @a init is not a list of pairs whose first
|
||||||
elements are strings. In this case, no object can be created. When such a
|
elements are strings. In this case, no object can be created. When such a
|
||||||
value is passed to @ref basic_json(std::initializer_list<basic_json>, bool, value_t),
|
value is passed to @ref basic_json(initializer_list_t, bool, value_t),
|
||||||
an array would have been created from the passed initializer list @a init.
|
an array would have been created from the passed initializer list @a init.
|
||||||
See example below.
|
See example below.
|
||||||
|
|
||||||
|
@ -8469,15 +8593,14 @@ class basic_json
|
||||||
@liveexample{The following code shows an example for the `object`
|
@liveexample{The following code shows an example for the `object`
|
||||||
function.,object}
|
function.,object}
|
||||||
|
|
||||||
@sa @ref basic_json(std::initializer_list<basic_json>, bool, value_t) --
|
@sa @ref basic_json(initializer_list_t, bool, value_t) --
|
||||||
create a JSON value from an initializer list
|
create a JSON value from an initializer list
|
||||||
@sa @ref array(std::initializer_list<basic_json>) -- create a JSON array
|
@sa @ref array(initializer_list_t) -- create a JSON array
|
||||||
value from an initializer list
|
value from an initializer list
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
static basic_json object(std::initializer_list<basic_json> init =
|
static basic_json object(initializer_list_t init = {})
|
||||||
std::initializer_list<basic_json>())
|
|
||||||
{
|
{
|
||||||
return basic_json(init, false, value_t::object);
|
return basic_json(init, false, value_t::object);
|
||||||
}
|
}
|
||||||
|
@ -8650,6 +8773,11 @@ class basic_json
|
||||||
// other constructors and destructor //
|
// other constructors and destructor //
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
|
basic_json(const detail::json_ref<basic_json>& ref)
|
||||||
|
: basic_json(ref.moved_or_copied())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief copy constructor
|
@brief copy constructor
|
||||||
|
|
||||||
|
@ -11450,7 +11578,7 @@ class basic_json
|
||||||
@brief add an object to an array
|
@brief add an object to an array
|
||||||
@copydoc push_back(basic_json&&)
|
@copydoc push_back(basic_json&&)
|
||||||
*/
|
*/
|
||||||
reference operator+=(basic_json&& val)
|
reference operator+=(basic_json && val)
|
||||||
{
|
{
|
||||||
push_back(std::move(val));
|
push_back(std::move(val));
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -11565,12 +11693,13 @@ class basic_json
|
||||||
@liveexample{The example shows how initializer lists are treated as
|
@liveexample{The example shows how initializer lists are treated as
|
||||||
objects when possible.,push_back__initializer_list}
|
objects when possible.,push_back__initializer_list}
|
||||||
*/
|
*/
|
||||||
void push_back(std::initializer_list<basic_json> init)
|
void push_back(initializer_list_t init)
|
||||||
{
|
{
|
||||||
if (is_object() and init.size() == 2 and init.begin()->is_string())
|
if (is_object() and init.size() == 2 and (*init.begin())->is_string())
|
||||||
{
|
{
|
||||||
const string_t key = *init.begin();
|
basic_json&& key = init.begin()->moved_or_copied();
|
||||||
push_back(typename object_t::value_type(key, *(init.begin() + 1)));
|
push_back(typename object_t::value_type(
|
||||||
|
std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -11580,9 +11709,9 @@ class basic_json
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief add an object to an object
|
@brief add an object to an object
|
||||||
@copydoc push_back(std::initializer_list<basic_json>)
|
@copydoc push_back(initializer_list_t)
|
||||||
*/
|
*/
|
||||||
reference operator+=(std::initializer_list<basic_json> init)
|
reference operator+=(initializer_list_t init)
|
||||||
{
|
{
|
||||||
push_back(init);
|
push_back(init);
|
||||||
return *this;
|
return *this;
|
||||||
|
@ -11867,7 +11996,7 @@ class basic_json
|
||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
iterator insert(const_iterator pos, std::initializer_list<basic_json> ilist)
|
iterator insert(const_iterator pos, initializer_list_t ilist)
|
||||||
{
|
{
|
||||||
// insert only works for arrays
|
// insert only works for arrays
|
||||||
if (JSON_UNLIKELY(not is_array()))
|
if (JSON_UNLIKELY(not is_array()))
|
||||||
|
@ -11883,7 +12012,7 @@ class basic_json
|
||||||
|
|
||||||
// insert to array and return iterator
|
// insert to array and return iterator
|
||||||
iterator result(this);
|
iterator result(this);
|
||||||
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist);
|
result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, ilist.begin(), ilist.end());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -842,8 +842,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l;
|
json j(json::initializer_list_t {});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::object);
|
CHECK(j.type() == json::value_t::object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,8 +859,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(json::array_t())};
|
json j(json::initializer_list_t {json(json::array_t())});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -876,8 +874,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(json::object_t())};
|
json j(json::initializer_list_t {json(json::object_t())});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -892,8 +889,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json("Hello world")};
|
json j(json::initializer_list_t {json("Hello world")});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -908,8 +904,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(true)};
|
json j(json::initializer_list_t {json(true)});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -924,8 +919,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(1)};
|
json j(json::initializer_list_t {json(1)});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -940,8 +934,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(1u)};
|
json j(json::initializer_list_t {json(1u)});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -956,8 +949,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {json(42.23)};
|
json j(json::initializer_list_t {json(42.23)});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -973,8 +965,7 @@ TEST_CASE("constructors")
|
||||||
{
|
{
|
||||||
SECTION("explicit")
|
SECTION("explicit")
|
||||||
{
|
{
|
||||||
std::initializer_list<json> l = {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()};
|
json j(json::initializer_list_t {1, 1u, 42.23, true, nullptr, json::object_t(), json::array_t()});
|
||||||
json j(l);
|
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1034,6 +1025,125 @@ TEST_CASE("constructors")
|
||||||
CHECK(j.type() == json::value_t::array);
|
CHECK(j.type() == json::value_t::array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("move from initializer_list")
|
||||||
|
{
|
||||||
|
SECTION("string")
|
||||||
|
{
|
||||||
|
// This should break through any short string optimization in std::string
|
||||||
|
std::string source(1024, '!');
|
||||||
|
const char* source_addr = source.data();
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j = {std::move(source)};
|
||||||
|
CHECK(j[0].get_ref<std::string const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j = {{"key", std::move(source)}};
|
||||||
|
CHECK(j["key"].get_ref<std::string const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (object key)")
|
||||||
|
{
|
||||||
|
json j = {{std::move(source), 42}};
|
||||||
|
CHECK(j.get_ref<json::object_t&>().begin()->first.data() == source_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("array")
|
||||||
|
{
|
||||||
|
json::array_t source = {1, 2, 3};
|
||||||
|
const json* source_addr = source.data();
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j {std::move(source)};
|
||||||
|
CHECK(j[0].get_ref<json::array_t const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j {{"key", std::move(source)}};
|
||||||
|
CHECK(j["key"].get_ref<json::array_t const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j = {std::move(source)};
|
||||||
|
CHECK(j[0].get_ref<json::array_t const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j = {{"key", std::move(source)}};
|
||||||
|
CHECK(j["key"].get_ref<json::array_t const&>().data() == source_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("object")
|
||||||
|
{
|
||||||
|
json::object_t source = {{"hello", "world"}};
|
||||||
|
const json* source_addr = &source.at("hello");
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j {std::move(source)};
|
||||||
|
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j {{"key", std::move(source)}};
|
||||||
|
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j = {std::move(source)};
|
||||||
|
CHECK(&(j[0].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j = {{"key", std::move(source)}};
|
||||||
|
CHECK(&(j["key"].get_ref<json::object_t const&>().at("hello")) == source_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("json")
|
||||||
|
{
|
||||||
|
json source {1, 2, 3};
|
||||||
|
const json* source_addr = &source[0];
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j {std::move(source), {}};
|
||||||
|
CHECK(&j[0][0] == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("constructor with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j {{"key", std::move(source)}};
|
||||||
|
CHECK(&j["key"][0] == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (array)")
|
||||||
|
{
|
||||||
|
json j = {std::move(source), {}};
|
||||||
|
CHECK(&j[0][0] == source_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("assignment with implicit types (object)")
|
||||||
|
{
|
||||||
|
json j = {{"key", std::move(source)}};
|
||||||
|
CHECK(&j["key"][0] == source_addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("create an array of n copies of a given value")
|
SECTION("create an array of n copies of a given value")
|
||||||
|
|
Loading…
Reference in a new issue