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
|
// very useful construct against boilerplate (more boilerplate needed than in
|
||||||
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
||||||
template <typename...> struct make_void
|
template <typename...> struct make_void
|
||||||
|
@ -411,9 +423,7 @@ struct is_compatible_basic_json_type
|
||||||
std::is_same<T, BasicJson>::value or
|
std::is_same<T, BasicJson>::value or
|
||||||
is_compatible_array_type<BasicJson, T>::value or
|
is_compatible_array_type<BasicJson, T>::value or
|
||||||
is_compatible_object_type<typename BasicJson::object_t, 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_integer_t, T>::value;
|
||||||
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
|
|
||||||
T>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename BasicJson, typename PrimitiveIterator>
|
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);
|
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>
|
template <typename Json>
|
||||||
void from_json(Json const& j, typename Json::boolean_t& b)
|
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);
|
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..)
|
// 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..
|
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
|
||||||
|
@ -1897,64 +1924,6 @@ class basic_json
|
||||||
assert_invariant();
|
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
|
@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
|
// very useful construct against boilerplate (more boilerplate needed than in
|
||||||
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
// C++17: http://en.cppreference.com/w/cpp/types/void_t)
|
||||||
template <typename...> struct make_void
|
template <typename...> struct make_void
|
||||||
|
@ -411,9 +423,7 @@ struct is_compatible_basic_json_type
|
||||||
std::is_same<T, BasicJson>::value or
|
std::is_same<T, BasicJson>::value or
|
||||||
is_compatible_array_type<BasicJson, T>::value or
|
is_compatible_array_type<BasicJson, T>::value or
|
||||||
is_compatible_object_type<typename BasicJson::object_t, 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_integer_t, T>::value;
|
||||||
is_compatible_integer_type<typename BasicJson::number_unsigned_t,
|
|
||||||
T>::value;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T, typename BasicJson, typename PrimitiveIterator>
|
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);
|
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>
|
template <typename Json>
|
||||||
void from_json(Json const& j, typename Json::boolean_t& b)
|
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);
|
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..)
|
// 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..
|
// note: Is it really necessary to provide explicit overloads for boolean_t etc..
|
||||||
|
@ -1898,64 +1925,6 @@ class basic_json
|
||||||
assert_invariant();
|
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
|
@brief create a container (array or object) from an initializer list
|
||||||
|
|
||||||
|
|
|
@ -483,11 +483,18 @@ TEST_CASE("Non-copyable types", "[udt]")
|
||||||
template <typename T, typename = typename std::enable_if<std::is_pod<T>::value>::type>
|
template <typename T, typename = typename std::enable_if<std::is_pod<T>::value>::type>
|
||||||
struct pod_serializer
|
struct pod_serializer
|
||||||
{
|
{
|
||||||
// I could forward-declare this struct, and add a basic_json alias
|
|
||||||
template <typename Json>
|
template <typename Json>
|
||||||
static void from_json(Json const& j , T& t)
|
static void from_json(Json const& j , T& t)
|
||||||
{
|
{
|
||||||
auto value = j.template get<std::uint64_t>();
|
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));
|
auto bytes = static_cast<char *>(static_cast<void *>(&value));
|
||||||
std::memcpy(&t, bytes, sizeof(value));
|
std::memcpy(&t, bytes, sizeof(value));
|
||||||
}
|
}
|
||||||
|
@ -501,8 +508,8 @@ struct pod_serializer
|
||||||
{
|
{
|
||||||
value |= bytes[i] << 8 * i;
|
value |= bytes[i] << 8 * i;
|
||||||
}
|
}
|
||||||
|
// same thing here
|
||||||
j = value;
|
nlohmann::to_json(j, value);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue