Support for integer types with non-trivial destructors, copy, and move constructors
This commit is contained in:
parent
d4daaa897f
commit
e15a17b437
@ -50,7 +50,7 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
|
||||
// overloads for basic_json template parameters
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||
enable_if_t < std::numeric_limits<ArithmeticType>::is_specialized&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
|
||||
@ -54,7 +54,7 @@ struct external_constructor<value_t::boolean>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::boolean;
|
||||
j.m_value = b;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(b);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -67,7 +67,7 @@ struct external_constructor<value_t::string>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::string;
|
||||
j.m_value = s;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(s);
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ struct external_constructor<value_t::string>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::string;
|
||||
j.m_value = std::move(s);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(std::move(s));
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -100,7 +100,7 @@ struct external_constructor<value_t::binary>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::binary;
|
||||
j.m_value = typename BasicJsonType::binary_t(b);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(typename BasicJsonType::binary_t(b));
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -109,7 +109,7 @@ struct external_constructor<value_t::binary>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::binary;
|
||||
j.m_value = typename BasicJsonType::binary_t(std::move(b));
|
||||
new (&j.m_value) typename BasicJsonType::json_value(typename BasicJsonType::binary_t(std::move(b)));
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -122,7 +122,7 @@ struct external_constructor<value_t::number_float>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_float;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -135,7 +135,7 @@ struct external_constructor<value_t::number_unsigned>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_unsigned;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -148,7 +148,7 @@ struct external_constructor<value_t::number_integer>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_integer;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -161,7 +161,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = arr;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(arr);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -171,7 +171,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = std::move(arr);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(std::move(arr));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -196,7 +196,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = value_t::array;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(value_t::array);
|
||||
j.m_value.array->reserve(arr.size());
|
||||
for (const bool x : arr)
|
||||
{
|
||||
@ -212,7 +212,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = value_t::array;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(value_t::array);
|
||||
j.m_value.array->resize(arr.size());
|
||||
if (arr.size() > 0)
|
||||
{
|
||||
@ -231,7 +231,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = obj;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(obj);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -241,7 +241,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = std::move(obj);
|
||||
new (&j.m_value) typename BasicJsonType:: json_value(std::move(obj));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -1250,7 +1250,7 @@ scan_number_done:
|
||||
if (errno == 0)
|
||||
{
|
||||
value_unsigned = static_cast<number_unsigned_t>(x);
|
||||
if (value_unsigned == x)
|
||||
if (static_cast<long long>(value_unsigned) == x)
|
||||
{
|
||||
return token_type::value_unsigned;
|
||||
}
|
||||
@ -1266,7 +1266,7 @@ scan_number_done:
|
||||
if (errno == 0)
|
||||
{
|
||||
value_integer = static_cast<number_integer_t>(x);
|
||||
if (value_integer == x)
|
||||
if (static_cast<long long>(value_integer) == x)
|
||||
{
|
||||
return token_type::value_integer;
|
||||
}
|
||||
|
||||
@ -432,8 +432,8 @@ struct is_compatible_integer_type_impl : std::false_type {};
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type_impl <
|
||||
RealIntegerType, CompatibleNumberIntegerType,
|
||||
enable_if_t < std::is_integral<RealIntegerType>::value&&
|
||||
std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||
enable_if_t < std::numeric_limits<RealIntegerType>::is_integer&&
|
||||
std::numeric_limits<CompatibleNumberIntegerType>::is_integer&&
|
||||
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
||||
{
|
||||
// is there an assert somewhere on overflows?
|
||||
|
||||
@ -675,13 +675,13 @@ class serializer
|
||||
}
|
||||
|
||||
// templates to avoid warnings about useless casts
|
||||
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
||||
template <typename NumberType, enable_if_t<std::numeric_limits<NumberType>::is_signed, int> = 0>
|
||||
bool is_negative_number(NumberType x)
|
||||
{
|
||||
return x < 0;
|
||||
return x < NumberType(0);
|
||||
}
|
||||
|
||||
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
|
||||
template < typename NumberType, enable_if_t < !std::numeric_limits<NumberType>::is_signed, int > = 0 >
|
||||
bool is_negative_number(NumberType /*unused*/)
|
||||
{
|
||||
return false;
|
||||
@ -697,7 +697,7 @@ class serializer
|
||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||
*/
|
||||
template < typename NumberType, detail::enable_if_t <
|
||||
std::is_integral<NumberType>::value ||
|
||||
std::numeric_limits<NumberType>::is_integer ||
|
||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||
std::is_same<NumberType, number_integer_t>::value ||
|
||||
std::is_same<NumberType, binary_char_t>::value,
|
||||
@ -721,7 +721,7 @@ class serializer
|
||||
};
|
||||
|
||||
// special case for "0"
|
||||
if (x == 0)
|
||||
if (x == NumberType(0))
|
||||
{
|
||||
o->write_character('0');
|
||||
return;
|
||||
@ -757,15 +757,16 @@ class serializer
|
||||
|
||||
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
|
||||
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
|
||||
while (abs_value >= 100)
|
||||
const NumberType hundred = 100;
|
||||
while (abs_value >= hundred)
|
||||
{
|
||||
const auto digits_index = static_cast<unsigned>((abs_value % 100));
|
||||
abs_value /= 100;
|
||||
const auto digits_index = static_cast<unsigned>((abs_value % hundred));
|
||||
abs_value /= hundred;
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][1];
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][0];
|
||||
}
|
||||
|
||||
if (abs_value >= 10)
|
||||
if (abs_value >= NumberType(10))
|
||||
{
|
||||
const auto digits_index = static_cast<unsigned>(abs_value);
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][1];
|
||||
|
||||
@ -474,7 +474,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
number_float_t number_float;
|
||||
|
||||
/// default constructor (for null values)
|
||||
json_value() = default;
|
||||
json_value() {};
|
||||
/// constructor for booleans
|
||||
json_value(boolean_t v) noexcept : boolean(v) {}
|
||||
/// constructor for numbers (integer)
|
||||
@ -585,6 +585,179 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// constructor for rvalue binary arrays (internal type)
|
||||
json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
|
||||
|
||||
/// User is responsible for calling `destroy` first to make this safe
|
||||
~json_value() {}
|
||||
|
||||
json_value& operator=(json_value&) = delete;
|
||||
|
||||
/// Copy from an existing value of type t
|
||||
json_value(value_t t, const json_value& v)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
new (this) json_value(v.object);
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
new (this) json_value(v.array);
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
new (this) json_value(v.string);
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
new (this) json_value(v.binary);
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
new (this) json_value(v.boolean);
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
new (this) json_value(v.number_integer);
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
new (this) json_value(v.number_unsigned);
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
new (this) json_value(v.number_float);
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Move from an existing value of type t
|
||||
json_value(value_t t, json_value&& v)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
new (this) json_value(std::move(v.object));
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
new (this) json_value(std::move(v.array));
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
new (this) json_value(std::move(v.string));
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
new (this) json_value(std::move(v.binary));
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
new (this) json_value(std::move(v.boolean));
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_integer));
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_unsigned));
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_float));
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
v.destroy(t);
|
||||
}
|
||||
|
||||
static void swap (value_t& t1, json_value& v1, value_t& t2, json_value& v2)
|
||||
{
|
||||
using std::swap;
|
||||
if (t1 == t2)
|
||||
{
|
||||
switch (t1)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
swap(v1.object, v2.object);
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
swap(v1.array, v2.array);
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
swap(v1.string, v2.string);
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
swap(v1.binary, v2.binary);
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
swap(v1.boolean, v2.boolean);
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
swap(v1.number_integer, v2.number_integer);
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
swap(v1.number_unsigned, v2.number_unsigned);
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
swap(v1.number_float, v2.number_float);
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
json_value tmp;
|
||||
new (&tmp) json_value(t1, std::move(v1));
|
||||
new (&v1) json_value(t2, std::move(v2));
|
||||
new (&v2) json_value(t1, std::move(tmp));
|
||||
swap(t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy(value_t t)
|
||||
{
|
||||
if (t == value_t::array || t == value_t::object)
|
||||
@ -670,11 +843,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::null:
|
||||
case value_t::boolean:
|
||||
{
|
||||
boolean.~boolean_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
number_integer.~number_integer_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
number_unsigned.~number_unsigned_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
number_float.~number_float_t();
|
||||
break;
|
||||
}
|
||||
case value_t::null:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
{
|
||||
@ -955,7 +1144,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
// the initializer list is a list of pairs -> create object
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value (value_t::object);
|
||||
|
||||
for (auto& element_ref : init)
|
||||
{
|
||||
@ -983,7 +1172,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = init;
|
||||
new (&res.m_value) json_value(init);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -994,7 +1183,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = binary_t(init, subtype);
|
||||
new (&res.m_value) json_value(binary_t(init, subtype));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1005,7 +1194,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = std::move(init);
|
||||
new (&res.m_value) json_value(std::move(init));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1016,7 +1205,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = binary_t(std::move(init), subtype);
|
||||
new (&res.m_value) json_value(binary_t(std::move(init), subtype));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -1119,7 +1308,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
m_value = *first.m_object->m_value.string;
|
||||
new (&m_value) json_value(*first.m_object->m_value.string);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1139,7 +1328,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *first.m_object->m_value.binary;
|
||||
new (&m_value) json_value(*first.m_object->m_value.binary);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1175,49 +1364,50 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
m_value = *other.m_value.object;
|
||||
|
||||
new (&m_value) json_value(*other.m_value.object);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
m_value = *other.m_value.array;
|
||||
new (&m_value) json_value(*other.m_value.array);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
m_value = *other.m_value.string;
|
||||
new (&m_value) json_value(*other.m_value.string);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean:
|
||||
{
|
||||
m_value = other.m_value.boolean;
|
||||
new (&m_value) json_value(other.m_value.boolean);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_integer:
|
||||
{
|
||||
m_value = other.m_value.number_integer;
|
||||
new (&m_value) json_value(other.m_value.number_integer);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
m_value = other.m_value.number_unsigned;
|
||||
new (&m_value) json_value(other.m_value.number_unsigned);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_float:
|
||||
{
|
||||
m_value = other.m_value.number_float;
|
||||
new (&m_value) json_value(other.m_value.number_float);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *other.m_value.binary;
|
||||
new (&m_value) json_value(*other.m_value.binary);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -1235,14 +1425,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
basic_json(basic_json&& other) noexcept
|
||||
: m_type(std::move(other.m_type)),
|
||||
m_value(std::move(other.m_value))
|
||||
m_value(other.m_type, other.m_value)
|
||||
{
|
||||
// check that passed value is valid
|
||||
other.assert_invariant(false);
|
||||
|
||||
// invalidate payload
|
||||
other.m_type = value_t::null;
|
||||
other.m_value = {};
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
@ -1260,10 +1449,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// check that passed value is valid
|
||||
other.assert_invariant();
|
||||
|
||||
using std::swap;
|
||||
swap(m_type, other.m_type);
|
||||
swap(m_value, other.m_value);
|
||||
|
||||
json_value::swap(m_type, m_value, other.m_type, other.m_value);
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
return *this;
|
||||
@ -3072,7 +3258,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -3105,7 +3291,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -3137,7 +3323,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value(value_t::object);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -3193,7 +3379,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -3218,7 +3404,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value(value_t::object);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -3441,8 +3627,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
)
|
||||
{
|
||||
std::swap(m_type, other.m_type);
|
||||
std::swap(m_value, other.m_value);
|
||||
json_value::swap(m_type, m_value, other.m_type, other.m_value);
|
||||
|
||||
set_parents();
|
||||
other.set_parents();
|
||||
@ -4162,7 +4347,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
value_t m_type = value_t::null;
|
||||
|
||||
/// the value of the current element
|
||||
json_value m_value = {};
|
||||
json_value m_value;
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
/// a pointer to a parent value (for debugging purposes)
|
||||
|
||||
@ -3627,8 +3627,8 @@ struct is_compatible_integer_type_impl : std::false_type {};
|
||||
template<typename RealIntegerType, typename CompatibleNumberIntegerType>
|
||||
struct is_compatible_integer_type_impl <
|
||||
RealIntegerType, CompatibleNumberIntegerType,
|
||||
enable_if_t < std::is_integral<RealIntegerType>::value&&
|
||||
std::is_integral<CompatibleNumberIntegerType>::value&&
|
||||
enable_if_t < std::numeric_limits<RealIntegerType>::is_integer&&
|
||||
std::numeric_limits<CompatibleNumberIntegerType>::is_integer&&
|
||||
!std::is_same<bool, CompatibleNumberIntegerType>::value >>
|
||||
{
|
||||
// is there an assert somewhere on overflows?
|
||||
@ -4302,7 +4302,7 @@ inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
|
||||
|
||||
// overloads for basic_json template parameters
|
||||
template < typename BasicJsonType, typename ArithmeticType,
|
||||
enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
|
||||
enable_if_t < std::numeric_limits<ArithmeticType>::is_specialized&&
|
||||
!std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
|
||||
int > = 0 >
|
||||
void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
|
||||
@ -5044,7 +5044,7 @@ struct external_constructor<value_t::boolean>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::boolean;
|
||||
j.m_value = b;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(b);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -5057,7 +5057,7 @@ struct external_constructor<value_t::string>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::string;
|
||||
j.m_value = s;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(s);
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -5066,7 +5066,7 @@ struct external_constructor<value_t::string>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::string;
|
||||
j.m_value = std::move(s);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(std::move(s));
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -5090,7 +5090,7 @@ struct external_constructor<value_t::binary>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::binary;
|
||||
j.m_value = typename BasicJsonType::binary_t(b);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(typename BasicJsonType::binary_t(b));
|
||||
j.assert_invariant();
|
||||
}
|
||||
|
||||
@ -5099,7 +5099,7 @@ struct external_constructor<value_t::binary>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::binary;
|
||||
j.m_value = typename BasicJsonType::binary_t(std::move(b));
|
||||
new (&j.m_value) typename BasicJsonType::json_value(typename BasicJsonType::binary_t(std::move(b)));
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -5112,7 +5112,7 @@ struct external_constructor<value_t::number_float>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_float;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -5125,7 +5125,7 @@ struct external_constructor<value_t::number_unsigned>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_unsigned;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -5138,7 +5138,7 @@ struct external_constructor<value_t::number_integer>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::number_integer;
|
||||
j.m_value = val;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(val);
|
||||
j.assert_invariant();
|
||||
}
|
||||
};
|
||||
@ -5151,7 +5151,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = arr;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(arr);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -5161,7 +5161,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = std::move(arr);
|
||||
new (&j.m_value) typename BasicJsonType::json_value(std::move(arr));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -5186,7 +5186,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = value_t::array;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(value_t::array);
|
||||
j.m_value.array->reserve(arr.size());
|
||||
for (const bool x : arr)
|
||||
{
|
||||
@ -5202,7 +5202,7 @@ struct external_constructor<value_t::array>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::array;
|
||||
j.m_value = value_t::array;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(value_t::array);
|
||||
j.m_value.array->resize(arr.size());
|
||||
if (arr.size() > 0)
|
||||
{
|
||||
@ -5221,7 +5221,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = obj;
|
||||
new (&j.m_value) typename BasicJsonType::json_value(obj);
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -5231,7 +5231,7 @@ struct external_constructor<value_t::object>
|
||||
{
|
||||
j.m_value.destroy(j.m_type);
|
||||
j.m_type = value_t::object;
|
||||
j.m_value = std::move(obj);
|
||||
new (&j.m_value) typename BasicJsonType:: json_value(std::move(obj));
|
||||
j.set_parents();
|
||||
j.assert_invariant();
|
||||
}
|
||||
@ -8193,7 +8193,7 @@ scan_number_done:
|
||||
if (errno == 0)
|
||||
{
|
||||
value_unsigned = static_cast<number_unsigned_t>(x);
|
||||
if (value_unsigned == x)
|
||||
if (static_cast<long long>(value_unsigned) == x)
|
||||
{
|
||||
return token_type::value_unsigned;
|
||||
}
|
||||
@ -8209,7 +8209,7 @@ scan_number_done:
|
||||
if (errno == 0)
|
||||
{
|
||||
value_integer = static_cast<number_integer_t>(x);
|
||||
if (value_integer == x)
|
||||
if (static_cast<long long>(value_integer) == x)
|
||||
{
|
||||
return token_type::value_integer;
|
||||
}
|
||||
@ -17948,13 +17948,13 @@ class serializer
|
||||
}
|
||||
|
||||
// templates to avoid warnings about useless casts
|
||||
template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
|
||||
template <typename NumberType, enable_if_t<std::numeric_limits<NumberType>::is_signed, int> = 0>
|
||||
bool is_negative_number(NumberType x)
|
||||
{
|
||||
return x < 0;
|
||||
return x < NumberType(0);
|
||||
}
|
||||
|
||||
template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
|
||||
template < typename NumberType, enable_if_t < !std::numeric_limits<NumberType>::is_signed, int > = 0 >
|
||||
bool is_negative_number(NumberType /*unused*/)
|
||||
{
|
||||
return false;
|
||||
@ -17970,7 +17970,7 @@ class serializer
|
||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||
*/
|
||||
template < typename NumberType, detail::enable_if_t <
|
||||
std::is_integral<NumberType>::value ||
|
||||
std::numeric_limits<NumberType>::is_integer ||
|
||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||
std::is_same<NumberType, number_integer_t>::value ||
|
||||
std::is_same<NumberType, binary_char_t>::value,
|
||||
@ -17994,7 +17994,7 @@ class serializer
|
||||
};
|
||||
|
||||
// special case for "0"
|
||||
if (x == 0)
|
||||
if (x == NumberType(0))
|
||||
{
|
||||
o->write_character('0');
|
||||
return;
|
||||
@ -18030,15 +18030,16 @@ class serializer
|
||||
|
||||
// Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
|
||||
// See: https://www.youtube.com/watch?v=o4-CwDo2zpg
|
||||
while (abs_value >= 100)
|
||||
const NumberType hundred = 100;
|
||||
while (abs_value >= hundred)
|
||||
{
|
||||
const auto digits_index = static_cast<unsigned>((abs_value % 100));
|
||||
abs_value /= 100;
|
||||
const auto digits_index = static_cast<unsigned>((abs_value % hundred));
|
||||
abs_value /= hundred;
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][1];
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][0];
|
||||
}
|
||||
|
||||
if (abs_value >= 10)
|
||||
if (abs_value >= NumberType(10))
|
||||
{
|
||||
const auto digits_index = static_cast<unsigned>(abs_value);
|
||||
*(--buffer_ptr) = digits_to_99[digits_index][1];
|
||||
@ -18991,7 +18992,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
number_float_t number_float;
|
||||
|
||||
/// default constructor (for null values)
|
||||
json_value() = default;
|
||||
json_value() {};
|
||||
/// constructor for booleans
|
||||
json_value(boolean_t v) noexcept : boolean(v) {}
|
||||
/// constructor for numbers (integer)
|
||||
@ -19102,6 +19103,179 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// constructor for rvalue binary arrays (internal type)
|
||||
json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
|
||||
|
||||
/// User is responsible for calling `destroy` first to make this safe
|
||||
~json_value() {}
|
||||
|
||||
json_value& operator=(json_value&) = delete;
|
||||
|
||||
/// Copy from an existing value of type t
|
||||
json_value(value_t t, const json_value& v)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
new (this) json_value(v.object);
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
new (this) json_value(v.array);
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
new (this) json_value(v.string);
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
new (this) json_value(v.binary);
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
new (this) json_value(v.boolean);
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
new (this) json_value(v.number_integer);
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
new (this) json_value(v.number_unsigned);
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
new (this) json_value(v.number_float);
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// Move from an existing value of type t
|
||||
json_value(value_t t, json_value&& v)
|
||||
{
|
||||
switch (t)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
new (this) json_value(std::move(v.object));
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
new (this) json_value(std::move(v.array));
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
new (this) json_value(std::move(v.string));
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
new (this) json_value(std::move(v.binary));
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
new (this) json_value(std::move(v.boolean));
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_integer));
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_unsigned));
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
new (this) json_value(std::move(v.number_float));
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
v.destroy(t);
|
||||
}
|
||||
|
||||
static void swap (value_t& t1, json_value& v1, value_t& t2, json_value& v2)
|
||||
{
|
||||
using std::swap;
|
||||
if (t1 == t2)
|
||||
{
|
||||
switch (t1)
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
swap(v1.object, v2.object);
|
||||
break;
|
||||
}
|
||||
case value_t::array:
|
||||
{
|
||||
swap(v1.array, v2.array);
|
||||
break;
|
||||
}
|
||||
case value_t::string:
|
||||
{
|
||||
swap(v1.string, v2.string);
|
||||
break;
|
||||
}
|
||||
case value_t::binary:
|
||||
{
|
||||
swap(v1.binary, v2.binary);
|
||||
break;
|
||||
}
|
||||
case value_t::boolean:
|
||||
{
|
||||
swap(v1.boolean, v2.boolean);
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
swap(v1.number_integer, v2.number_integer);
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
swap(v1.number_unsigned, v2.number_unsigned);
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
swap(v1.number_float, v2.number_float);
|
||||
break;
|
||||
}
|
||||
case value_t::discarded:
|
||||
case value_t::null:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
json_value tmp;
|
||||
new (&tmp) json_value(t1, std::move(v1));
|
||||
new (&v1) json_value(t2, std::move(v2));
|
||||
new (&v2) json_value(t1, std::move(tmp));
|
||||
swap(t1, t2);
|
||||
}
|
||||
}
|
||||
|
||||
void destroy(value_t t)
|
||||
{
|
||||
if (t == value_t::array || t == value_t::object)
|
||||
@ -19187,11 +19361,27 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::null:
|
||||
case value_t::boolean:
|
||||
{
|
||||
boolean.~boolean_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_integer:
|
||||
{
|
||||
number_integer.~number_integer_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
number_unsigned.~number_unsigned_t();
|
||||
break;
|
||||
}
|
||||
case value_t::number_float:
|
||||
{
|
||||
number_float.~number_float_t();
|
||||
break;
|
||||
}
|
||||
case value_t::null:
|
||||
case value_t::discarded:
|
||||
default:
|
||||
{
|
||||
@ -19472,7 +19662,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
// the initializer list is a list of pairs -> create object
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value (value_t::object);
|
||||
|
||||
for (auto& element_ref : init)
|
||||
{
|
||||
@ -19500,7 +19690,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = init;
|
||||
new (&res.m_value) json_value(init);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -19511,7 +19701,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = binary_t(init, subtype);
|
||||
new (&res.m_value) json_value(binary_t(init, subtype));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -19522,7 +19712,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = std::move(init);
|
||||
new (&res.m_value) json_value(std::move(init));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -19533,7 +19723,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = binary_t(std::move(init), subtype);
|
||||
new (&res.m_value) json_value(binary_t(std::move(init), subtype));
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -19636,7 +19826,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
m_value = *first.m_object->m_value.string;
|
||||
new (&m_value) json_value(*first.m_object->m_value.string);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -19656,7 +19846,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *first.m_object->m_value.binary;
|
||||
new (&m_value) json_value(*first.m_object->m_value.binary);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -19692,49 +19882,50 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
{
|
||||
case value_t::object:
|
||||
{
|
||||
m_value = *other.m_value.object;
|
||||
|
||||
new (&m_value) json_value(*other.m_value.object);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
m_value = *other.m_value.array;
|
||||
new (&m_value) json_value(*other.m_value.array);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::string:
|
||||
{
|
||||
m_value = *other.m_value.string;
|
||||
new (&m_value) json_value(*other.m_value.string);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean:
|
||||
{
|
||||
m_value = other.m_value.boolean;
|
||||
new (&m_value) json_value(other.m_value.boolean);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_integer:
|
||||
{
|
||||
m_value = other.m_value.number_integer;
|
||||
new (&m_value) json_value(other.m_value.number_integer);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_unsigned:
|
||||
{
|
||||
m_value = other.m_value.number_unsigned;
|
||||
new (&m_value) json_value(other.m_value.number_unsigned);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::number_float:
|
||||
{
|
||||
m_value = other.m_value.number_float;
|
||||
new (&m_value) json_value(other.m_value.number_float);
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *other.m_value.binary;
|
||||
new (&m_value) json_value(*other.m_value.binary);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -19752,14 +19943,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/basic_json/
|
||||
basic_json(basic_json&& other) noexcept
|
||||
: m_type(std::move(other.m_type)),
|
||||
m_value(std::move(other.m_value))
|
||||
m_value(other.m_type, other.m_value)
|
||||
{
|
||||
// check that passed value is valid
|
||||
other.assert_invariant(false);
|
||||
|
||||
// invalidate payload
|
||||
other.m_type = value_t::null;
|
||||
other.m_value = {};
|
||||
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
@ -19777,10 +19967,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
// check that passed value is valid
|
||||
other.assert_invariant();
|
||||
|
||||
using std::swap;
|
||||
swap(m_type, other.m_type);
|
||||
swap(m_value, other.m_value);
|
||||
|
||||
json_value::swap(m_type, m_value, other.m_type, other.m_value);
|
||||
set_parents();
|
||||
assert_invariant();
|
||||
return *this;
|
||||
@ -21589,7 +21776,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -21622,7 +21809,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -21654,7 +21841,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value(value_t::object);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -21710,7 +21897,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::array;
|
||||
m_value = value_t::array;
|
||||
new (&m_value) json_value(value_t::array);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -21735,7 +21922,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
if (is_null())
|
||||
{
|
||||
m_type = value_t::object;
|
||||
m_value = value_t::object;
|
||||
new (&m_value) json_value(value_t::object);
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
@ -21958,8 +22145,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
std::is_nothrow_move_assignable<json_value>::value
|
||||
)
|
||||
{
|
||||
std::swap(m_type, other.m_type);
|
||||
std::swap(m_value, other.m_value);
|
||||
json_value::swap(m_type, m_value, other.m_type, other.m_value);
|
||||
|
||||
set_parents();
|
||||
other.set_parents();
|
||||
@ -22679,7 +22865,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||
value_t m_type = value_t::null;
|
||||
|
||||
/// the value of the current element
|
||||
json_value m_value = {};
|
||||
json_value m_value;
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
/// a pointer to a parent value (for debugging purposes)
|
||||
|
||||
114
tests/src/unit-custom-integer.cpp
Normal file
114
tests/src/unit-custom-integer.cpp
Normal file
@ -0,0 +1,114 @@
|
||||
/*
|
||||
__ _____ _____ _____
|
||||
__| | __| | | | JSON for Modern C++ (test suite)
|
||||
| | |__ | | | | | | version 3.10.5
|
||||
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
|
||||
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||
SPDX-License-Identifier: MIT
|
||||
Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
using nlohmann::json;
|
||||
|
||||
/// A `int
|
||||
template<typename T>
|
||||
class heap_int
|
||||
{
|
||||
public:
|
||||
std::unique_ptr<T> val;
|
||||
operator T() const
|
||||
{
|
||||
return val == nullptr ? 0 : *val;
|
||||
}
|
||||
// operator double() const { return static_cast<T>(val); }
|
||||
heap_int() : val() {}
|
||||
heap_int(T val) : val(new T(val)) {}
|
||||
heap_int(heap_int&&) = default;
|
||||
heap_int(const heap_int& other) : val(new T(static_cast<T>(other))) {}
|
||||
|
||||
heap_int& operator=(const heap_int& other)
|
||||
{
|
||||
val = std::unique_ptr<T>(new T(static_cast<T>(other)));
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const heap_int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) == static_cast<T>(other);
|
||||
}
|
||||
bool operator<(const int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) < other;
|
||||
}
|
||||
heap_int operator+(const heap_int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) + static_cast<T>(other);
|
||||
}
|
||||
bool operator%(const heap_int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) % static_cast<T>(other.val);
|
||||
}
|
||||
heap_int& operator/=(const heap_int& other)
|
||||
{
|
||||
if (val != nullptr)
|
||||
{
|
||||
*val /= static_cast<T>(other.val);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
bool operator<(const heap_int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) < static_cast<T>(other.val);
|
||||
}
|
||||
bool operator<=(const heap_int& other) const
|
||||
{
|
||||
return static_cast<T>(*this) <= static_cast<T>(other.val);
|
||||
}
|
||||
|
||||
friend void swap(heap_int& self, heap_int& other)
|
||||
{
|
||||
swap(self.val, other.val);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T> class std::numeric_limits<heap_int<T>>
|
||||
{
|
||||
public:
|
||||
static constexpr bool is_signed = std::numeric_limits<T>::is_signed;
|
||||
static constexpr bool is_integer = std::numeric_limits<T>::is_integer;
|
||||
static constexpr bool is_specialized = std::numeric_limits<T>::is_specialized;
|
||||
};
|
||||
|
||||
TEST_CASE("custom integer type")
|
||||
{
|
||||
using json = nlohmann::basic_json <
|
||||
std::map, std::vector, std::string, bool, heap_int<std::int64_t>, std::uint64_t, double, std::allocator >;
|
||||
// create a JSON value with different types
|
||||
std::string data = "[1,2,3,4]";
|
||||
json as_json = json::parse(data.begin(), data.end());
|
||||
heap_int<std::int64_t> i = as_json[2];
|
||||
heap_int<std::int64_t> three = 3;
|
||||
CHECK(i == three);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user