replace constructor by from/to_json: number_unsigned_t
This commit forces a design change in custom JSONSerializer, which might be temporary
This commit is contained in:
parent
d257149f36
commit
a32de3b528
3 changed files with 73 additions and 128 deletions
91
src/json.hpp
91
src/json.hpp
|
@ -248,6 +248,18 @@ struct external_constructor<value_t::number_float>
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct external_constructor<value_t::number_unsigned>
|
||||
{
|
||||
template <typename Json>
|
||||
static void construct(Json &j, typename Json::number_unsigned_t val) noexcept
|
||||
{
|
||||
j.m_type = value_t::number_unsigned;
|
||||
j.m_value = val;
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
|
||||
// very useful construct against boilerplate (more boilerplate needed than in
|
||||
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
||||
template <typename...> struct make_void
|
||||
|
@ -411,9 +423,7 @@ struct is_compatible_basic_json_type
|
|||
std::is_same<T, BasicJson>::value or
|
||||
is_compatible_array_type<BasicJson, T>::value or
|
||||
is_compatible_object_type<typename BasicJson::object_t, T>::value or
|
||||
is_compatible_integer_type<typename BasicJson::number_integer_t, T>::value or
|
||||
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
|
||||
T>::value;
|
||||
is_compatible_integer_type<typename BasicJson::number_integer_t, T>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename BasicJson, typename PrimitiveIterator>
|
||||
|
@ -526,6 +536,17 @@ void to_json(Json &j, CompatibleNumberFloatType val) noexcept
|
|||
external_constructor<value_t::number_float>::construct(j, val);
|
||||
}
|
||||
|
||||
|
||||
template <
|
||||
typename Json, typename CompatibleNumberUnsignedType,
|
||||
enable_if_t<is_compatible_integer_type<typename Json::number_unsigned_t,
|
||||
CompatibleNumberUnsignedType>::value,
|
||||
int> = 0>
|
||||
void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept
|
||||
{
|
||||
external_constructor<value_t::number_unsigned>::construct(j, val);
|
||||
}
|
||||
|
||||
template <typename Json>
|
||||
void from_json(Json const& j, typename Json::boolean_t& b)
|
||||
{
|
||||
|
@ -548,6 +569,12 @@ void from_json(Json const& j, typename Json::number_float_t& val)
|
|||
get_arithmetic_value(j, val);
|
||||
}
|
||||
|
||||
template <typename Json>
|
||||
void from_json(Json const& j, typename Json::number_unsigned_t& val)
|
||||
{
|
||||
get_arithmetic_value(j, val);
|
||||
}
|
||||
|
||||
// overload for arithmetic types, not chosen for basic_json template arguments (BooleanType, etc..)
|
||||
//
|
||||
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
|
||||
|
@ -1897,64 +1924,6 @@ class basic_json
|
|||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create an unsigned integer number (explicit)
|
||||
|
||||
Create an unsigned integer number JSON value with a given content.
|
||||
|
||||
@tparam T helper type to compare number_unsigned_t and unsigned int (not
|
||||
visible in) the interface.
|
||||
|
||||
@param[in] val an integer to create a JSON number from
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
|
||||
value (unsigned integer) from a compatible number type
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template<typename T, typename std::enable_if<
|
||||
not (std::is_same<T, int>::value) and
|
||||
std::is_same<T, number_unsigned_t>::value, int>::type = 0>
|
||||
basic_json(const number_unsigned_t val) noexcept
|
||||
: m_type(value_t::number_unsigned), m_value(val)
|
||||
{
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create an unsigned number (implicit)
|
||||
|
||||
Create an unsigned number JSON value with a given content. This
|
||||
constructor allows any type @a CompatibleNumberUnsignedType that can be
|
||||
used to construct values of type @ref number_unsigned_t.
|
||||
|
||||
@tparam CompatibleNumberUnsignedType An integer type which is compatible
|
||||
to @ref number_unsigned_t. Examples may include the types `unsigned int`,
|
||||
`uint32_t`, or `unsigned short`.
|
||||
|
||||
@param[in] val an unsigned integer to create a JSON number from
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@sa @ref basic_json(const number_unsigned_t) -- create a number value
|
||||
(unsigned)
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template <
|
||||
typename CompatibleNumberUnsignedType,
|
||||
enable_if_t<detail::is_compatible_integer_type<
|
||||
number_unsigned_t, CompatibleNumberUnsignedType>::value,
|
||||
int> = 0 >
|
||||
basic_json(const CompatibleNumberUnsignedType val) noexcept
|
||||
: m_type(value_t::number_unsigned),
|
||||
m_value(static_cast<number_unsigned_t>(val))
|
||||
{
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a container (array or object) from an initializer list
|
||||
|
||||
|
|
|
@ -248,6 +248,18 @@ struct external_constructor<value_t::number_float>
|
|||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct external_constructor<value_t::number_unsigned>
|
||||
{
|
||||
template <typename Json>
|
||||
static void construct(Json &j, typename Json::number_unsigned_t val) noexcept
|
||||
{
|
||||
j.m_type = value_t::number_unsigned;
|
||||
j.m_value = val;
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
|
||||
// very useful construct against boilerplate (more boilerplate needed than in
|
||||
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
||||
template <typename...> struct make_void
|
||||
|
@ -411,9 +423,7 @@ struct is_compatible_basic_json_type
|
|||
std::is_same<T, BasicJson>::value or
|
||||
is_compatible_array_type<BasicJson, T>::value or
|
||||
is_compatible_object_type<typename BasicJson::object_t, T>::value or
|
||||
is_compatible_integer_type<typename BasicJson::number_integer_t, T>::value or
|
||||
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
|
||||
T>::value;
|
||||
is_compatible_integer_type<typename BasicJson::number_integer_t, T>::value;
|
||||
};
|
||||
|
||||
template <typename T, typename BasicJson, typename PrimitiveIterator>
|
||||
|
@ -526,6 +536,17 @@ void to_json(Json &j, CompatibleNumberFloatType val) noexcept
|
|||
external_constructor<value_t::number_float>::construct(j, val);
|
||||
}
|
||||
|
||||
|
||||
template <
|
||||
typename Json, typename CompatibleNumberUnsignedType,
|
||||
enable_if_t<is_compatible_integer_type<typename Json::number_unsigned_t,
|
||||
CompatibleNumberUnsignedType>::value,
|
||||
int> = 0>
|
||||
void to_json(Json &j, CompatibleNumberUnsignedType val) noexcept
|
||||
{
|
||||
external_constructor<value_t::number_unsigned>::construct(j, val);
|
||||
}
|
||||
|
||||
template <typename Json>
|
||||
void from_json(Json const& j, typename Json::boolean_t& b)
|
||||
{
|
||||
|
@ -548,6 +569,12 @@ void from_json(Json const& j, typename Json::number_float_t& val)
|
|||
get_arithmetic_value(j, val);
|
||||
}
|
||||
|
||||
template <typename Json>
|
||||
void from_json(Json const& j, typename Json::number_unsigned_t& val)
|
||||
{
|
||||
get_arithmetic_value(j, val);
|
||||
}
|
||||
|
||||
// overload for arithmetic types, not chosen for basic_json template arguments (BooleanType, etc..)
|
||||
//
|
||||
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
|
||||
|
@ -1898,64 +1925,6 @@ class basic_json
|
|||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create an unsigned integer number (explicit)
|
||||
|
||||
Create an unsigned integer number JSON value with a given content.
|
||||
|
||||
@tparam T helper type to compare number_unsigned_t and unsigned int (not
|
||||
visible in) the interface.
|
||||
|
||||
@param[in] val an integer to create a JSON number from
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@sa @ref basic_json(const CompatibleNumberUnsignedType) -- create a number
|
||||
value (unsigned integer) from a compatible number type
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template<typename T, typename std::enable_if<
|
||||
not (std::is_same<T, int>::value) and
|
||||
std::is_same<T, number_unsigned_t>::value, int>::type = 0>
|
||||
basic_json(const number_unsigned_t val) noexcept
|
||||
: m_type(value_t::number_unsigned), m_value(val)
|
||||
{
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create an unsigned number (implicit)
|
||||
|
||||
Create an unsigned number JSON value with a given content. This
|
||||
constructor allows any type @a CompatibleNumberUnsignedType that can be
|
||||
used to construct values of type @ref number_unsigned_t.
|
||||
|
||||
@tparam CompatibleNumberUnsignedType An integer type which is compatible
|
||||
to @ref number_unsigned_t. Examples may include the types `unsigned int`,
|
||||
`uint32_t`, or `unsigned short`.
|
||||
|
||||
@param[in] val an unsigned integer to create a JSON number from
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@sa @ref basic_json(const number_unsigned_t) -- create a number value
|
||||
(unsigned)
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template <
|
||||
typename CompatibleNumberUnsignedType,
|
||||
enable_if_t<detail::is_compatible_integer_type<
|
||||
number_unsigned_t, CompatibleNumberUnsignedType>::value,
|
||||
int> = 0 >
|
||||
basic_json(const CompatibleNumberUnsignedType val) noexcept
|
||||
: m_type(value_t::number_unsigned),
|
||||
m_value(static_cast<number_unsigned_t>(val))
|
||||
{
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief create a container (array or object) from an initializer list
|
||||
|
||||
|
|
|
@ -483,13 +483,20 @@ TEST_CASE("Non-copyable types", "[udt]")
|
|||
template <typename T, typename = typename std::enable_if<std::is_pod<T>::value>::type>
|
||||
struct pod_serializer
|
||||
{
|
||||
// I could forward-declare this struct, and add a basic_json alias
|
||||
template <typename Json>
|
||||
static void from_json(Json const& j , T& t)
|
||||
{
|
||||
auto value = j.template get<std::uint64_t>();
|
||||
auto bytes = static_cast<char*>(static_cast<void*>(&value));
|
||||
std::memcpy(&t, bytes, sizeof(value));
|
||||
std::uint64_t value;
|
||||
// Why cannot we simply use: j.get<std::uint64_t>() ?
|
||||
// Well, with the current experiment, the get method looks for a from_json function, which we are currently defining!
|
||||
// This would end up in a stack overflow. Calling nlohmann::from_json is a workaround.
|
||||
// I shall find a good way to avoid this once all constructors are converted to free methods
|
||||
//
|
||||
// In short, constructing a json by constructor calls to_json
|
||||
// calling get calls from_json, for now, we cannot do this in custom serializers
|
||||
nlohmann::from_json(j, value);
|
||||
auto bytes = static_cast<char *>(static_cast<void *>(&value));
|
||||
std::memcpy(&t, bytes, sizeof(value));
|
||||
}
|
||||
|
||||
template <typename Json>
|
||||
|
@ -501,8 +508,8 @@ struct pod_serializer
|
|||
{
|
||||
value |= bytes[i] << 8 * i;
|
||||
}
|
||||
|
||||
j = value;
|
||||
// same thing here
|
||||
nlohmann::to_json(j, value);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue