Merge 827b15a0ba into f854410542
This commit is contained in:
commit
8776431855
82
src/json.hpp
82
src/json.hpp
@ -106,6 +106,43 @@ static bool approx(const T a, const T b)
|
|||||||
{
|
{
|
||||||
return not (a > b or a < b);
|
return not (a > b or a < b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief Type Trait to convert a type to a void for SFINAE purposes
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct void_converter
|
||||||
|
{
|
||||||
|
using type = void;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Type to help determine between a map or unordered-map type for the
|
||||||
|
// object_t type alias. Takes advantage of the fact that an unordered_map
|
||||||
|
// has a hasher member type
|
||||||
|
template<template<typename...> class ObjectType, class Key, class Value,
|
||||||
|
template<typename> class AllocatorType, typename Enable = void>
|
||||||
|
struct object_t_helper
|
||||||
|
{
|
||||||
|
using type = ObjectType<
|
||||||
|
Key,
|
||||||
|
Value,
|
||||||
|
std::less<Key>,
|
||||||
|
AllocatorType<std::pair<Key,Value>>>;
|
||||||
|
};
|
||||||
|
// Specialization that works for the 'unordered_map' type
|
||||||
|
template<template<typename...> class ObjectType, class Key, class Value,
|
||||||
|
template<typename> class AllocatorType>
|
||||||
|
struct object_t_helper<ObjectType, Key, Value, AllocatorType,
|
||||||
|
typename void_converter<typename ObjectType<char,char>::hasher>::type
|
||||||
|
>
|
||||||
|
{
|
||||||
|
using type = ObjectType<
|
||||||
|
Key,
|
||||||
|
Value,
|
||||||
|
std::hash<Key>,
|
||||||
|
std::equal_to<Key>,
|
||||||
|
AllocatorType<std::pair<Key,Value>>>;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -334,11 +371,12 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
using object_t = ObjectType<StringType,
|
using object_t = typename object_t_helper<
|
||||||
basic_json,
|
ObjectType,
|
||||||
std::less<StringType>,
|
StringType,
|
||||||
AllocatorType<std::pair<const StringType,
|
basic_json,
|
||||||
basic_json>>>;
|
AllocatorType
|
||||||
|
>::type;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief a type for an array
|
@brief a type for an array
|
||||||
@ -960,7 +998,7 @@ class basic_json
|
|||||||
*/
|
*/
|
||||||
template <class CompatibleObjectType, typename
|
template <class CompatibleObjectType, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
std::is_constructible<typename object_t::key_type, typename CompatibleObjectType::key_type>::value and
|
std::is_constructible<StringType, typename CompatibleObjectType::key_type>::value and
|
||||||
std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
|
std::is_constructible<basic_json, typename CompatibleObjectType::mapped_type>::value, int>::type
|
||||||
= 0>
|
= 0>
|
||||||
basic_json(const CompatibleObjectType& val)
|
basic_json(const CompatibleObjectType& val)
|
||||||
@ -2170,7 +2208,7 @@ class basic_json
|
|||||||
/// get an object (explicit)
|
/// get an object (explicit)
|
||||||
template <class T, typename
|
template <class T, typename
|
||||||
std::enable_if<
|
std::enable_if<
|
||||||
std::is_convertible<typename object_t::key_type, typename T::key_type>::value and
|
std::is_convertible<StringType, typename T::key_type>::value and
|
||||||
std::is_convertible<basic_json_t, typename T::mapped_type>::value
|
std::is_convertible<basic_json_t, typename T::mapped_type>::value
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
T get_impl(T*) const
|
T get_impl(T*) const
|
||||||
@ -2807,7 +2845,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
reference at(const typename object_t::key_type& key)
|
reference at(const StringType& key)
|
||||||
{
|
{
|
||||||
// at only works for objects
|
// at only works for objects
|
||||||
if (is_object())
|
if (is_object())
|
||||||
@ -2855,7 +2893,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
const_reference at(const typename object_t::key_type& key) const
|
const_reference at(const StringType& key) const
|
||||||
{
|
{
|
||||||
// at only works for objects
|
// at only works for objects
|
||||||
if (is_object())
|
if (is_object())
|
||||||
@ -2988,7 +3026,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
reference operator[](const typename object_t::key_type& key)
|
reference operator[](const StringType& key)
|
||||||
{
|
{
|
||||||
// implicitly convert null to object
|
// implicitly convert null to object
|
||||||
if (is_null())
|
if (is_null())
|
||||||
@ -3036,7 +3074,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
const_reference operator[](const typename object_t::key_type& key) const
|
const_reference operator[](const StringType& key) const
|
||||||
{
|
{
|
||||||
// [] only works for objects
|
// [] only works for objects
|
||||||
if (is_object())
|
if (is_object())
|
||||||
@ -3199,7 +3237,7 @@ class basic_json
|
|||||||
std::enable_if<
|
std::enable_if<
|
||||||
std::is_convertible<basic_json_t, ValueType>::value
|
std::is_convertible<basic_json_t, ValueType>::value
|
||||||
, int>::type = 0>
|
, int>::type = 0>
|
||||||
ValueType value(const typename object_t::key_type& key, ValueType default_value) const
|
ValueType value(const StringType& key, ValueType default_value) const
|
||||||
{
|
{
|
||||||
// at only works for objects
|
// at only works for objects
|
||||||
if (is_object())
|
if (is_object())
|
||||||
@ -3225,7 +3263,7 @@ class basic_json
|
|||||||
@brief overload for a default value of type const char*
|
@brief overload for a default value of type const char*
|
||||||
@copydoc basic_json::value()
|
@copydoc basic_json::value()
|
||||||
*/
|
*/
|
||||||
string_t value(const typename object_t::key_type& key, const char* default_value) const
|
string_t value(const StringType& key, const char* default_value) const
|
||||||
{
|
{
|
||||||
return value(key, string_t(default_value));
|
return value(key, string_t(default_value));
|
||||||
}
|
}
|
||||||
@ -3539,7 +3577,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
size_type erase(const typename object_t::key_type& key)
|
size_type erase(const StringType& key)
|
||||||
{
|
{
|
||||||
// this erase only works for objects
|
// this erase only works for objects
|
||||||
if (is_object())
|
if (is_object())
|
||||||
@ -3613,7 +3651,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
iterator find(typename object_t::key_type key)
|
iterator find(StringType key)
|
||||||
{
|
{
|
||||||
auto result = end();
|
auto result = end();
|
||||||
|
|
||||||
@ -3630,7 +3668,7 @@ class basic_json
|
|||||||
@brief find an element in a JSON object
|
@brief find an element in a JSON object
|
||||||
@copydoc find(typename object_t::key_type)
|
@copydoc find(typename object_t::key_type)
|
||||||
*/
|
*/
|
||||||
const_iterator find(typename object_t::key_type key) const
|
const_iterator find(StringType key) const
|
||||||
{
|
{
|
||||||
auto result = cend();
|
auto result = cend();
|
||||||
|
|
||||||
@ -3661,7 +3699,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
size_type count(typename object_t::key_type key) const
|
size_type count(StringType key) const
|
||||||
{
|
{
|
||||||
// return 0 for all nonobject types
|
// return 0 for all nonobject types
|
||||||
assert(not is_object() or m_value.object != nullptr);
|
assert(not is_object() or m_value.object != nullptr);
|
||||||
@ -4306,7 +4344,7 @@ class basic_json
|
|||||||
|
|
||||||
@since version 1.0.0
|
@since version 1.0.0
|
||||||
*/
|
*/
|
||||||
void push_back(const typename object_t::value_type& val)
|
void push_back(const std::pair<StringType, basic_json>& val)
|
||||||
{
|
{
|
||||||
// push_back only works for null objects or objects
|
// push_back only works for null objects or objects
|
||||||
if (not(is_null() or is_object()))
|
if (not(is_null() or is_object()))
|
||||||
@ -4328,9 +4366,9 @@ class basic_json
|
|||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief add an object to an object
|
@brief add an object to an object
|
||||||
@copydoc push_back(const typename object_t::value_type&)
|
@copydoc push_back(const std::pair<StringType, basic_json>&)
|
||||||
*/
|
*/
|
||||||
reference operator+=(const typename object_t::value_type& val)
|
reference operator+=(const std::pair<StringType, basic_json>& val)
|
||||||
{
|
{
|
||||||
push_back(val);
|
push_back(val);
|
||||||
return operator[](val.first);
|
return operator[](val.first);
|
||||||
@ -6266,7 +6304,7 @@ class basic_json
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// return the key of an object iterator
|
/// return the key of an object iterator
|
||||||
typename object_t::key_type key() const
|
StringType key() const
|
||||||
{
|
{
|
||||||
assert(m_object != nullptr);
|
assert(m_object != nullptr);
|
||||||
|
|
||||||
@ -6525,7 +6563,7 @@ class basic_json
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// return the key of an object iterator
|
/// return the key of an object iterator
|
||||||
typename object_t::key_type key() const
|
StringType key() const
|
||||||
{
|
{
|
||||||
auto it = --this->base();
|
auto it = --this->base();
|
||||||
return it.key();
|
return it.key();
|
||||||
|
|||||||
@ -11500,6 +11500,12 @@ TEST_CASE("regression tests")
|
|||||||
CHECK(s2 == "value");
|
CHECK(s2 == "value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("issue #164 - std::unordered_map cannot be used as ObjectType")
|
||||||
|
{
|
||||||
|
// create JSON class with std::unordered_map instead of a std::map
|
||||||
|
nlohmann::basic_json<std::unordered_map> unordered_json;
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("character following a surrogate pair is skipped")
|
SECTION("character following a surrogate pair is skipped")
|
||||||
{
|
{
|
||||||
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
|
CHECK(json::parse("\"\\ud80c\\udc60abc\"").get<json::string_t>() == u8"\U00013060abc");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user