mirror of
https://github.com/nlohmann/json.git
synced 2025-08-07 18:02:57 +03:00
Merge branch 'develop' into issues/1457
This commit is contained in:
@@ -97,6 +97,9 @@ default; will be used in @ref number_integer_t)
|
||||
`uint64_t` by default; will be used in @ref number_unsigned_t)
|
||||
@tparam NumberFloatType type for JSON floating-point numbers (`double` by
|
||||
default; will be used in @ref number_float_t)
|
||||
@tparam BinaryType type for packed binary data for compatibility with binary
|
||||
serialization formats (`std::vector<std::uint8_t>` by default; will be used in
|
||||
@ref binary_t)
|
||||
@tparam AllocatorType type of the allocator to use (`std::allocator` by
|
||||
default)
|
||||
@tparam JSONSerializer the serializer to resolve internal calls to `to_json()`
|
||||
@@ -830,6 +833,100 @@ class basic_json
|
||||
*/
|
||||
using number_float_t = NumberFloatType;
|
||||
|
||||
/*!
|
||||
@brief a type for a packed binary type
|
||||
|
||||
This type is a type designed to carry binary data that appears in various
|
||||
serialized formats, such as CBOR's Major Type 2, MessagePack's bin, and
|
||||
BSON's generic binary subtype. This type is NOT a part of standard JSON and
|
||||
exists solely for compatibility with these binary types. As such, it is
|
||||
simply defined as an ordered sequence of zero or more byte values.
|
||||
|
||||
Additionally, as an implementation detail, the subtype of the binary data is
|
||||
carried around as a `unint8_t`, which is compatible with both of the binary
|
||||
data formats that use binary subtyping, (though the specific numbering is
|
||||
incompatible with each other, and it is up to the user to translate between
|
||||
them).
|
||||
|
||||
[CBOR's RFC 7049](https://tools.ietf.org/html/rfc7049) describes this type
|
||||
as:
|
||||
> Major type 2: a byte string. The string's length in bytes is
|
||||
> represented following the rules for positive integers (major type
|
||||
> 0).
|
||||
|
||||
[MessagePack's documentation on the bin type
|
||||
family](https://github.com/msgpack/msgpack/blob/master/spec.md#bin-format-family)
|
||||
describes this type as:
|
||||
> Bin format family stores an byte array in 2, 3, or 5 bytes of extra bytes
|
||||
> in addition to the size of the byte array.
|
||||
|
||||
[BSON's specifications](http://bsonspec.org/spec.html) describe several
|
||||
binary types; however, this type is intended to represent the generic binary
|
||||
type which has the description:
|
||||
> Generic binary subtype - This is the most commonly used binary subtype and
|
||||
> should be the 'default' for drivers and tools.
|
||||
|
||||
None of these impose any limitations on the internal representation other
|
||||
than the basic unit of storage be some type of array whose parts are
|
||||
decomposible into bytes.
|
||||
|
||||
The default representation of this binary format is a
|
||||
`std::vector<std::uint8_t>`, which is a very common way to represent a byte
|
||||
array in modern C++.
|
||||
|
||||
#### Default type
|
||||
|
||||
The default values for @a BinaryType is `std::vector<std::uint8_t>`
|
||||
|
||||
#### Storage
|
||||
|
||||
Binary Arrays are stored as pointers in a @ref basic_json type. That is,
|
||||
for any access to array values, a pointer of the type `binary_t*` must be
|
||||
dereferenced.
|
||||
|
||||
@sa @ref array_t -- type for an array value
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
using binary_t = BinaryType;
|
||||
|
||||
/*!
|
||||
@brief an internal type for a backed binary type
|
||||
|
||||
This type is designed to be `binary_t` but with the subtype implementation
|
||||
detail. This type exists so that the user does not have to specify a struct
|
||||
his- or herself with a specific naming scheme in order to override the
|
||||
binary type. I.e. it's for ease of use.
|
||||
*/
|
||||
struct internal_binary_t : public BinaryType
|
||||
{
|
||||
using BinaryType::BinaryType;
|
||||
internal_binary_t() noexcept(noexcept(BinaryType()))
|
||||
: BinaryType()
|
||||
{}
|
||||
internal_binary_t(const BinaryType& bint) noexcept(noexcept(BinaryType(bint)))
|
||||
: BinaryType(bint)
|
||||
{}
|
||||
internal_binary_t(BinaryType&& bint) noexcept(noexcept(BinaryType(std::move(bint))))
|
||||
: BinaryType(std::move(bint))
|
||||
{}
|
||||
internal_binary_t(const BinaryType& bint, std::uint8_t st) noexcept(noexcept(BinaryType(bint)))
|
||||
: BinaryType(bint)
|
||||
, subtype(st)
|
||||
, has_subtype(true)
|
||||
{}
|
||||
internal_binary_t(BinaryType&& bint, std::uint8_t st) noexcept(noexcept(BinaryType(std::move(bint))))
|
||||
: BinaryType(std::move(bint))
|
||||
, subtype(st)
|
||||
, has_subtype(true)
|
||||
{}
|
||||
|
||||
// TOOD: If minimum C++ version is ever bumped to C++17, this field
|
||||
// deserves to be a std::optional
|
||||
std::uint8_t subtype = 0;
|
||||
bool has_subtype = false;
|
||||
};
|
||||
|
||||
/// @}
|
||||
|
||||
private:
|
||||
@@ -872,6 +969,7 @@ class basic_json
|
||||
number | number_integer | @ref number_integer_t
|
||||
number | number_unsigned | @ref number_unsigned_t
|
||||
number | number_float | @ref number_float_t
|
||||
binary | binary | pointer to @ref internal_binary_t
|
||||
null | null | *no value is stored*
|
||||
|
||||
@note Variable-length types (objects, arrays, and strings) are stored as
|
||||
@@ -888,6 +986,8 @@ class basic_json
|
||||
array_t* array;
|
||||
/// string (stored with pointer to save storage)
|
||||
string_t* string;
|
||||
/// binary (stored with pointer to save storage)
|
||||
internal_binary_t* binary;
|
||||
/// boolean
|
||||
boolean_t boolean;
|
||||
/// number (integer)
|
||||
@@ -930,6 +1030,12 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
binary = create<internal_binary_t>();
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::boolean:
|
||||
{
|
||||
boolean = boolean_t(false);
|
||||
@@ -1008,6 +1114,30 @@ class basic_json
|
||||
array = create<array_t>(std::move(value));
|
||||
}
|
||||
|
||||
/// constructor for binary arrays
|
||||
json_value(const binary_t& value)
|
||||
{
|
||||
binary = create<internal_binary_t>(value);
|
||||
}
|
||||
|
||||
/// constructor for rvalue binary arrays
|
||||
json_value(binary_t&& value)
|
||||
{
|
||||
binary = create<internal_binary_t>(std::move(value));
|
||||
}
|
||||
|
||||
/// constructor for binary arrays (internal type)
|
||||
json_value(const internal_binary_t& value)
|
||||
{
|
||||
binary = create<internal_binary_t>(value);
|
||||
}
|
||||
|
||||
/// constructor for rvalue binary arrays (internal type)
|
||||
json_value(internal_binary_t&& value)
|
||||
{
|
||||
binary = create<internal_binary_t>(std::move(value));
|
||||
}
|
||||
|
||||
void destroy(value_t t) noexcept
|
||||
{
|
||||
// flatten the current json_value to a heap-allocated stack
|
||||
@@ -1083,6 +1213,14 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
AllocatorType<internal_binary_t> alloc;
|
||||
std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
|
||||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
break;
|
||||
@@ -1105,6 +1243,7 @@ class basic_json
|
||||
assert(m_type != value_t::object or m_value.object != nullptr);
|
||||
assert(m_type != value_t::array or m_value.array != nullptr);
|
||||
assert(m_type != value_t::string or m_value.string != nullptr);
|
||||
assert(m_type != value_t::binary or m_value.binary != nullptr);
|
||||
}
|
||||
|
||||
public:
|
||||
@@ -1203,6 +1342,7 @@ class basic_json
|
||||
number | `0`
|
||||
object | `{}`
|
||||
array | `[]`
|
||||
binary | empty array
|
||||
|
||||
@param[in] v the type of the value to create
|
||||
|
||||
@@ -1274,6 +1414,12 @@ class basic_json
|
||||
@ref number_float_t, and all convertible number types such as `int`,
|
||||
`size_t`, `int64_t`, `float` or `double` can be used.
|
||||
- **boolean**: @ref boolean_t / `bool` can be used.
|
||||
- **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
|
||||
unfortunately because string literals cannot be distinguished from binary
|
||||
character arrays by the C++ type system, all types compatible with `const
|
||||
char*` will be directed to the string constructor instead. This is both
|
||||
for backwards compatibility, and due to the fact that a binary type is not
|
||||
a standard JSON type.
|
||||
|
||||
See the examples below.
|
||||
|
||||
@@ -1355,6 +1501,7 @@ class basic_json
|
||||
using other_string_t = typename BasicJsonType::string_t;
|
||||
using other_object_t = typename BasicJsonType::object_t;
|
||||
using other_array_t = typename BasicJsonType::array_t;
|
||||
using other_binary_t = typename BasicJsonType::internal_binary_t;
|
||||
|
||||
switch (val.type())
|
||||
{
|
||||
@@ -1379,6 +1526,9 @@ class basic_json
|
||||
case value_t::array:
|
||||
JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
|
||||
break;
|
||||
case value_t::binary:
|
||||
JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
|
||||
break;
|
||||
case value_t::null:
|
||||
*this = nullptr;
|
||||
break;
|
||||
@@ -1517,6 +1667,96 @@ class basic_json
|
||||
assert_invariant();
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief explicitly create a binary array from an already constructed copy of
|
||||
its base type
|
||||
|
||||
Creates a JSON binary array value from a given `binary_t`. Binary values are
|
||||
part of various binary formats, such as CBOR, MsgPack, and BSON. And this
|
||||
constructor is used to create a value for serialization to those formats.
|
||||
|
||||
@note Note, this function exists because of the difficulty in correctly
|
||||
specifying the correct template overload in the standard value ctor, as both
|
||||
JSON arrays and JSON binary arrays are backed with some form of a
|
||||
`std::vector`. Because JSON binary arrays are a non-standard extension it
|
||||
was decided that it would be best to prevent automatic initialization of a
|
||||
binary array type, for backwards compatibility and so it does not happen on
|
||||
accident.
|
||||
|
||||
@param[in] init `binary_t` with JSON values to create a binary array from
|
||||
|
||||
@return JSON binary array value
|
||||
|
||||
@complexity Linear in the size of @a init.
|
||||
|
||||
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
|
||||
changes to any JSON value.
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json binary_array(const binary_t& init)
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = init;
|
||||
return res;
|
||||
}
|
||||
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json binary_array(const binary_t& init, std::uint8_t subtype)
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = internal_binary_t(init, subtype);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief explicitly create a binary array from an already constructed rvalue
|
||||
copy of its base type
|
||||
|
||||
Creates a JSON binary array value from a given `binary_t`. Binary values are
|
||||
part of various binary formats, such as CBOR, MsgPack, and BSON. And this
|
||||
constructor is used to create a value for serialization to those formats.
|
||||
|
||||
@note Note, this function exists because of the difficulty in correctly
|
||||
specifying the correct template overload in the standard value ctor, as both
|
||||
JSON arrays and JSON binary arrays are backed with some form of a
|
||||
`std::vector`. Because JSON binary arrays are a non-standard extension it
|
||||
was decided that it would be best to prevent automatic initialization of a
|
||||
binary array type, for backwards compatibility and so it doesn't happen on
|
||||
accident.
|
||||
|
||||
@param[in] init `binary_t` with JSON values to create a binary array from
|
||||
|
||||
@return JSON binary array value
|
||||
|
||||
@complexity Linear in the size of @a init.
|
||||
|
||||
@exceptionsafety Strong guarantee: if an exception is thrown, there are no
|
||||
changes to any JSON value.
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json binary_array(binary_t&& init)
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = std::move(init);
|
||||
return res;
|
||||
}
|
||||
|
||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||
static basic_json binary_array(binary_t&& init, std::uint8_t subtype)
|
||||
{
|
||||
auto res = basic_json();
|
||||
res.m_type = value_t::binary;
|
||||
res.m_value = internal_binary_t(std::move(init), subtype);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief explicitly create an array from an initializer list
|
||||
|
||||
@@ -1772,6 +2012,12 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *first.m_object->m_value.binary;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
JSON_THROW(invalid_iterator::create(206, "cannot construct with iterators from " +
|
||||
std::string(first.m_object->type_name())));
|
||||
@@ -1785,10 +2031,10 @@ class basic_json
|
||||
// other constructors and destructor //
|
||||
///////////////////////////////////////
|
||||
|
||||
/// @private
|
||||
basic_json(const detail::json_ref<basic_json>& ref)
|
||||
: basic_json(ref.moved_or_copied())
|
||||
{}
|
||||
template <typename JsonRef,
|
||||
detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
|
||||
std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
|
||||
basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
|
||||
|
||||
/*!
|
||||
@brief copy constructor
|
||||
@@ -1865,6 +2111,12 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value = *other.m_value.binary;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -2005,6 +2257,11 @@ class basic_json
|
||||
possible values: `strict` (throws and exception in case a decoding error
|
||||
occurs; default), `replace` (replace invalid UTF-8 sequences with U+FFFD),
|
||||
and `ignore` (ignore invalid UTF-8 sequences during serialization).
|
||||
@param[in] serialize_binary Whether or not to allow serialization of binary
|
||||
types to JSON. Because binary types are non-standard, this will produce
|
||||
non-conformant JSON, and is disabled by default. This flag is primarily
|
||||
useful for debugging. Will output the binary value as a list of 8-bit
|
||||
numbers prefixed by "b" (e.g. "bindata" = b[3, 0, 42, 255]).
|
||||
|
||||
@return string containing the serialization of the JSON value
|
||||
|
||||
@@ -2029,18 +2286,19 @@ class basic_json
|
||||
string_t dump(const int indent = -1,
|
||||
const char indent_char = ' ',
|
||||
const bool ensure_ascii = false,
|
||||
const error_handler_t error_handler = error_handler_t::strict) const
|
||||
const error_handler_t error_handler = error_handler_t::strict,
|
||||
const bool serialize_binary = false) const
|
||||
{
|
||||
string_t result;
|
||||
serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
|
||||
|
||||
if (indent >= 0)
|
||||
{
|
||||
s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
|
||||
s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent), 0, serialize_binary);
|
||||
}
|
||||
else
|
||||
{
|
||||
s.dump(*this, false, ensure_ascii, 0);
|
||||
s.dump(*this, false, ensure_ascii, 0, 0, serialize_binary);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -2063,6 +2321,7 @@ class basic_json
|
||||
number (floating-point) | value_t::number_float
|
||||
object | value_t::object
|
||||
array | value_t::array
|
||||
binary | value_t::binary
|
||||
discarded | value_t::discarded
|
||||
|
||||
@complexity Constant.
|
||||
@@ -2105,12 +2364,13 @@ class basic_json
|
||||
@sa @ref is_string() -- returns whether JSON value is a string
|
||||
@sa @ref is_boolean() -- returns whether JSON value is a boolean
|
||||
@sa @ref is_number() -- returns whether JSON value is a number
|
||||
@sa @ref is_binary() -- returns whether JSON value is a binary array
|
||||
|
||||
@since version 1.0.0
|
||||
*/
|
||||
constexpr bool is_primitive() const noexcept
|
||||
{
|
||||
return is_null() or is_string() or is_boolean() or is_number();
|
||||
return is_null() or is_string() or is_boolean() or is_number() or is_binary();
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -2365,6 +2625,28 @@ class basic_json
|
||||
return m_type == value_t::string;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return whether value is a binary array
|
||||
|
||||
This function returns true if and only if the JSON value is a binary array.
|
||||
|
||||
@return `true` if type is binary array, `false` otherwise.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this member function never throws
|
||||
exceptions.
|
||||
|
||||
@liveexample{The following code exemplifies `is_binary()` for all JSON
|
||||
types.,is_binary}
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
constexpr bool is_binary() const noexcept
|
||||
{
|
||||
return m_type == value_t::binary;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return whether value is discarded
|
||||
|
||||
@@ -2520,6 +2802,30 @@ class basic_json
|
||||
return is_number_float() ? &m_value.number_float : nullptr;
|
||||
}
|
||||
|
||||
/// get a pointer to the value (binary)
|
||||
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
|
||||
{
|
||||
return is_binary() ? reinterpret_cast<binary_t*>(m_value.binary) : nullptr;
|
||||
}
|
||||
|
||||
/// get a pointer to the value (binary)
|
||||
constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
|
||||
{
|
||||
return is_binary() ? m_value.binary : nullptr;
|
||||
}
|
||||
|
||||
/// get a pointer to the value (binary)
|
||||
internal_binary_t* get_impl_ptr(internal_binary_t* /*unused*/) noexcept
|
||||
{
|
||||
return is_binary() ? m_value.binary : nullptr;
|
||||
}
|
||||
|
||||
/// get a pointer to the value (binary)
|
||||
constexpr const internal_binary_t* get_impl_ptr(const internal_binary_t* /*unused*/) const noexcept
|
||||
{
|
||||
return is_binary() ? m_value.binary : nullptr;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief helper function to implement get_ref()
|
||||
|
||||
@@ -2933,12 +3239,9 @@ class basic_json
|
||||
not std::is_same<ValueType, detail::json_ref<basic_json>>::value and
|
||||
not std::is_same<ValueType, typename string_t::value_type>::value and
|
||||
not detail::is_basic_json<ValueType>::value
|
||||
|
||||
#ifndef _MSC_VER // fix for issue #167 operator<< ambiguity under VS2015
|
||||
and not std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>::value
|
||||
#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) and _MSC_VER <= 1914))
|
||||
and not std::is_same<ValueType, typename std::string_view>::value
|
||||
#endif
|
||||
#endif
|
||||
and detail::is_detected<detail::get_template_function, const basic_json_t&, ValueType>::value
|
||||
, int >::type = 0 >
|
||||
@@ -3570,6 +3873,120 @@ class basic_json
|
||||
return value(ptr, string_t(default_value));
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return the binary subtype
|
||||
|
||||
Returns the numerical subtype of the JSON value, if the JSON value is of
|
||||
type "binary", and it has a subtype. If it does not have a subtype (or the
|
||||
object is not of type binary) this function will return size_t(-1) as a
|
||||
sentinel value.
|
||||
|
||||
@return the numerical subtype of the binary JSON value
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this member function never throws
|
||||
exceptions.
|
||||
|
||||
@sa @ref set_subtype() -- sets the binary subtype
|
||||
@sa @ref clear_subtype() -- clears the binary subtype
|
||||
@sa @ref has_subtype() -- returns whether or not the binary value has a
|
||||
subtype
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
std::size_t get_subtype() const noexcept
|
||||
{
|
||||
if (is_binary() and m_value.binary->has_subtype)
|
||||
{
|
||||
return m_value.binary->subtype;
|
||||
}
|
||||
|
||||
return std::size_t(-1);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief sets the binary subtype
|
||||
|
||||
Sets the binary subtype of the JSON value, also flags a binary JSON value as
|
||||
having a subtype, which has implications for serialization to msgpack (will
|
||||
prefer ext file formats over bin). If the JSON value is not a binary value,
|
||||
this function does nothing.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this member function never throws
|
||||
exceptions.
|
||||
|
||||
@sa @ref get_subtype() -- return the binary subtype
|
||||
@sa @ref clear_subtype() -- clears the binary subtype
|
||||
@sa @ref has_subtype() -- returns whether or not the binary value has a
|
||||
subtype
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
|
||||
void set_subtype(std::uint8_t subtype) noexcept
|
||||
{
|
||||
if (is_binary())
|
||||
{
|
||||
m_value.binary->has_subtype = true;
|
||||
m_value.binary->subtype = subtype;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief clears the binary subtype
|
||||
|
||||
Clears the binary subtype of the JSON value, also flags a binary JSON value
|
||||
as not having a subtype, which has implications for serialization to msgpack
|
||||
(will prefer bin file formats over ext). If the JSON value is not a binary
|
||||
value, this function does nothing.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this member function never throws
|
||||
exceptions.
|
||||
|
||||
@sa @ref get_subtype() -- return the binary subtype
|
||||
@sa @ref set_subtype() -- sets the binary subtype
|
||||
@sa @ref has_subtype() -- returns whether or not the binary value has a
|
||||
subtype
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
void clear_subtype() noexcept
|
||||
{
|
||||
if (is_binary())
|
||||
{
|
||||
m_value.binary->has_subtype = false;
|
||||
m_value.binary->subtype = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief return whether or not the binary subtype has a value
|
||||
|
||||
Returns whether or not the binary subtype has a value.
|
||||
|
||||
@return whether or not the binary subtype has a value.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@exceptionsafety No-throw guarantee: this member function never throws
|
||||
exceptions.
|
||||
|
||||
@sa @ref get_subtype() -- return the binary subtype
|
||||
@sa @ref set_subtype() -- sets the binary subtype
|
||||
@sa @ref clear_subtype() -- clears the binary subtype
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
bool has_subtype() const noexcept
|
||||
{
|
||||
return is_binary() and m_value.binary->has_subtype;
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief access the first element
|
||||
|
||||
@@ -3577,8 +3994,8 @@ class basic_json
|
||||
container `c`, the expression `c.front()` is equivalent to `*c.begin()`.
|
||||
|
||||
@return In case of a structured type (array or object), a reference to the
|
||||
first element is returned. In case of number, string, or boolean values, a
|
||||
reference to the value is returned.
|
||||
first element is returned. In case of number, string, boolean, or binary
|
||||
values, a reference to the value is returned.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@@ -3620,8 +4037,8 @@ class basic_json
|
||||
@endcode
|
||||
|
||||
@return In case of a structured type (array or object), a reference to the
|
||||
last element is returned. In case of number, string, or boolean values, a
|
||||
reference to the value is returned.
|
||||
last element is returned. In case of number, string, boolean, or binary
|
||||
values, a reference to the value is returned.
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@@ -3687,7 +4104,7 @@ class basic_json
|
||||
@complexity The complexity depends on the type:
|
||||
- objects: amortized constant
|
||||
- arrays: linear in distance between @a pos and the end of the container
|
||||
- strings: linear in the length of the string
|
||||
- strings and binary: linear in the length of the member
|
||||
- other types: constant
|
||||
|
||||
@liveexample{The example shows the result of `erase()` for different JSON
|
||||
@@ -3723,6 +4140,7 @@ class basic_json
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
case value_t::string:
|
||||
case value_t::binary:
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(not pos.m_it.primitive_iterator.is_begin()))
|
||||
{
|
||||
@@ -3736,6 +4154,13 @@ class basic_json
|
||||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
|
||||
m_value.string = nullptr;
|
||||
}
|
||||
else if (is_binary())
|
||||
{
|
||||
AllocatorType<internal_binary_t> alloc;
|
||||
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
|
||||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
|
||||
m_value.binary = nullptr;
|
||||
}
|
||||
|
||||
m_type = value_t::null;
|
||||
assert_invariant();
|
||||
@@ -3793,7 +4218,7 @@ class basic_json
|
||||
- objects: `log(size()) + std::distance(first, last)`
|
||||
- arrays: linear in the distance between @a first and @a last, plus linear
|
||||
in the distance between @a last and end of the container
|
||||
- strings: linear in the length of the string
|
||||
- strings and binary: linear in the length of the member
|
||||
- other types: constant
|
||||
|
||||
@liveexample{The example shows the result of `erase()` for different JSON
|
||||
@@ -3828,6 +4253,7 @@ class basic_json
|
||||
case value_t::number_integer:
|
||||
case value_t::number_unsigned:
|
||||
case value_t::string:
|
||||
case value_t::binary:
|
||||
{
|
||||
if (JSON_HEDLEY_LIKELY(not first.m_it.primitive_iterator.is_begin()
|
||||
or not last.m_it.primitive_iterator.is_end()))
|
||||
@@ -3842,6 +4268,13 @@ class basic_json
|
||||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
|
||||
m_value.string = nullptr;
|
||||
}
|
||||
else if (is_binary())
|
||||
{
|
||||
AllocatorType<internal_binary_t> alloc;
|
||||
std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
|
||||
std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
|
||||
m_value.binary = nullptr;
|
||||
}
|
||||
|
||||
m_type = value_t::null;
|
||||
assert_invariant();
|
||||
@@ -4561,6 +4994,7 @@ class basic_json
|
||||
boolean | `false`
|
||||
string | `false`
|
||||
number | `false`
|
||||
binary | `false`
|
||||
object | result of function `object_t::empty()`
|
||||
array | result of function `array_t::empty()`
|
||||
|
||||
@@ -4632,6 +5066,7 @@ class basic_json
|
||||
boolean | `1`
|
||||
string | `1`
|
||||
number | `1`
|
||||
binary | `1`
|
||||
object | result of function object_t::size()
|
||||
array | result of function array_t::size()
|
||||
|
||||
@@ -4706,6 +5141,7 @@ class basic_json
|
||||
boolean | `1` (same as `size()`)
|
||||
string | `1` (same as `size()`)
|
||||
number | `1` (same as `size()`)
|
||||
binary | `1` (same as `size()`)
|
||||
object | result of function `object_t::max_size()`
|
||||
array | result of function `array_t::max_size()`
|
||||
|
||||
@@ -4778,6 +5214,7 @@ class basic_json
|
||||
boolean | `false`
|
||||
string | `""`
|
||||
number | `0`
|
||||
binary | An empty byte vector
|
||||
object | `{}`
|
||||
array | `[]`
|
||||
|
||||
@@ -4835,6 +5272,12 @@ class basic_json
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::binary:
|
||||
{
|
||||
m_value.binary->clear();
|
||||
break;
|
||||
}
|
||||
|
||||
case value_t::array:
|
||||
{
|
||||
m_value.array->clear();
|
||||
@@ -4890,9 +5333,7 @@ class basic_json
|
||||
|
||||
// add element to array (move semantics)
|
||||
m_value.array->push_back(std::move(val));
|
||||
// invalidate object: mark it null so we do not call the destructor
|
||||
// cppcheck-suppress accessMoved
|
||||
val.m_type = value_t::null;
|
||||
// if val is moved from, basic_json move constructor marks it null so we do not call the destructor
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -5631,6 +6072,39 @@ class basic_json
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief exchanges the values
|
||||
|
||||
Exchanges the contents of a JSON string with those of @a other. Does not
|
||||
invoke any move, copy, or swap operations on individual elements. All
|
||||
iterators and references remain valid. The past-the-end iterator is
|
||||
invalidated.
|
||||
|
||||
@param[in,out] other binary to exchange the contents with
|
||||
|
||||
@throw type_error.310 when JSON value is not a string; example: `"cannot
|
||||
use swap() with boolean"`
|
||||
|
||||
@complexity Constant.
|
||||
|
||||
@liveexample{The example below shows how strings can be swapped with
|
||||
`swap()`.,swap__binary_t}
|
||||
|
||||
@since version 3.8.0
|
||||
*/
|
||||
void swap(binary_t& other)
|
||||
{
|
||||
// swap only works for strings
|
||||
if (JSON_HEDLEY_LIKELY(is_binary()))
|
||||
{
|
||||
std::swap(*(m_value.binary), other);
|
||||
}
|
||||
else
|
||||
{
|
||||
JSON_THROW(type_error::create(310, "cannot use swap() with " + std::string(type_name())));
|
||||
}
|
||||
}
|
||||
|
||||
/// @}
|
||||
|
||||
public:
|
||||
@@ -5649,13 +6123,13 @@ class basic_json
|
||||
their stored values are the same according to their respective
|
||||
`operator==`.
|
||||
- Integer and floating-point numbers are automatically converted before
|
||||
comparison. Note than two NaN values are always treated as unequal.
|
||||
comparison. Note that two NaN values are always treated as unequal.
|
||||
- Two JSON null values are equal.
|
||||
|
||||
@note Floating-point inside JSON values numbers are compared with
|
||||
`json::number_float_t::operator==` which is `double::operator==` by
|
||||
default. To compare floating-point while respecting an epsilon, an alternative
|
||||
[comparison function](https://github.com/mariokonrad/marnav/blob/master/src/marnav/math/floatingpoint.hpp#L34-#L39)
|
||||
[comparison function](https://github.com/mariokonrad/marnav/blob/master/include/marnav/math/floatingpoint.hpp#L34-#L39)
|
||||
could be used, for instance
|
||||
@code {.cpp}
|
||||
template<typename T, typename = typename std::enable_if<std::is_floating_point<T>::value, T>::type>
|
||||
@@ -5664,6 +6138,22 @@ class basic_json
|
||||
return std::abs(a - b) <= epsilon;
|
||||
}
|
||||
@endcode
|
||||
Or you can self-defined operator equal function like this:
|
||||
@code {.cpp}
|
||||
bool my_equal(const_reference lhs, const_reference rhs) {
|
||||
const auto lhs_type lhs.type();
|
||||
const auto rhs_type rhs.type();
|
||||
if (lhs_type == rhs_type) {
|
||||
switch(lhs_type)
|
||||
// self_defined case
|
||||
case value_t::number_float:
|
||||
return std::abs(lhs - rhs) <= std::numeric_limits<float>::epsilon();
|
||||
// other cases remain the same with the original
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
@endcode
|
||||
|
||||
@note NaN values never compare equal to themselves or to other NaN values.
|
||||
|
||||
@@ -5713,6 +6203,9 @@ class basic_json
|
||||
case value_t::number_float:
|
||||
return lhs.m_value.number_float == rhs.m_value.number_float;
|
||||
|
||||
case value_t::binary:
|
||||
return *lhs.m_value.binary == *rhs.m_value.binary;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -5873,6 +6366,9 @@ class basic_json
|
||||
case value_t::number_float:
|
||||
return (lhs.m_value.number_float) < (rhs.m_value.number_float);
|
||||
|
||||
case value_t::binary:
|
||||
return (*lhs.m_value.binary) < (*rhs.m_value.binary);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
@@ -6317,7 +6813,6 @@ class basic_json
|
||||
const bool strict = true)
|
||||
{
|
||||
assert(sax);
|
||||
|
||||
auto ia = i.get();
|
||||
return format == input_format_t::json
|
||||
? parser(std::move(ia)).sax_parse(sax, strict)
|
||||
@@ -6472,6 +6967,7 @@ class basic_json
|
||||
number | `"number"` (for all number types)
|
||||
object | `"object"`
|
||||
array | `"array"`
|
||||
binary | `"binary"`
|
||||
discarded | `"discarded"`
|
||||
|
||||
@exceptionsafety No-throw guarantee: this function never throws exceptions.
|
||||
@@ -6503,6 +6999,8 @@ class basic_json
|
||||
return "string";
|
||||
case value_t::boolean:
|
||||
return "boolean";
|
||||
case value_t::binary:
|
||||
return "binary";
|
||||
case value_t::discarded:
|
||||
return "discarded";
|
||||
default:
|
||||
@@ -6578,6 +7076,11 @@ class basic_json
|
||||
object | *size*: 256..65535 | map (2 bytes follow) | 0xB9
|
||||
object | *size*: 65536..4294967295 | map (4 bytes follow) | 0xBA
|
||||
object | *size*: 4294967296..18446744073709551615 | map (8 bytes follow) | 0xBB
|
||||
binary | *size*: 0..23 | byte string | 0x40..0x57
|
||||
binary | *size*: 23..255 | byte string (1 byte follow) | 0x58
|
||||
binary | *size*: 256..65535 | byte string (2 bytes follow) | 0x59
|
||||
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
||||
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
||||
|
||||
@note The mapping is **complete** in the sense that any JSON value type
|
||||
can be converted to a CBOR value.
|
||||
@@ -6587,10 +7090,10 @@ class basic_json
|
||||
function which serializes NaN or Infinity to `null`.
|
||||
|
||||
@note The following CBOR types are not used in the conversion:
|
||||
- byte strings (0x40..0x5F)
|
||||
- UTF-8 strings terminated by "break" (0x7F)
|
||||
- arrays terminated by "break" (0x9F)
|
||||
- maps terminated by "break" (0xBF)
|
||||
- byte strings terminated by "break" (0x5F)
|
||||
- date/time (0xC0..0xC1)
|
||||
- bignum (0xC2..0xC3)
|
||||
- decimal fraction (0xC4)
|
||||
@@ -6677,20 +7180,21 @@ class basic_json
|
||||
object | *size*: 0..15 | fix map | 0x80..0x8F
|
||||
object | *size*: 16..65535 | map 16 | 0xDE
|
||||
object | *size*: 65536..4294967295 | map 32 | 0xDF
|
||||
binary | *size*: 0..255 | bin 8 | 0xC4
|
||||
binary | *size*: 256..65535 | bin 16 | 0xC5
|
||||
binary | *size*: 65536..4294967295 | bin 32 | 0xC6
|
||||
|
||||
@note The mapping is **complete** in the sense that any JSON value type
|
||||
can be converted to a MessagePack value.
|
||||
|
||||
@note The following values can **not** be converted to a MessagePack value:
|
||||
- strings with more than 4294967295 bytes
|
||||
- byte strings with more than 4294967295 bytes
|
||||
- arrays with more than 4294967295 elements
|
||||
- objects with more than 4294967295 elements
|
||||
|
||||
@note The following MessagePack types are not used in the conversion:
|
||||
- bin 8 - bin 32 (0xC4..0xC6)
|
||||
- ext 8 - ext 32 (0xC7..0xC9)
|
||||
- float 32 (0xCA)
|
||||
- fixext 1 - fixext 16 (0xD4..0xD8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
@@ -6793,6 +7297,12 @@ class basic_json
|
||||
the benefit of this parameter is that the receiving side is
|
||||
immediately informed on the number of elements of the container.
|
||||
|
||||
@note If the JSON data contains the binary type, the value stored is a list
|
||||
of integers, as suggested by the UBJSON documentation. In particular,
|
||||
this means that serialization and the deserialization of a JSON
|
||||
containing binary values into UBJSON and back will result in a
|
||||
different JSON object.
|
||||
|
||||
@param[in] j JSON value to serialize
|
||||
@param[in] use_size whether to add size annotations to container types
|
||||
@param[in] use_type whether to add type annotations to container types
|
||||
@@ -6857,6 +7367,7 @@ class basic_json
|
||||
string | *any value* | string | 0x02
|
||||
array | *any value* | document | 0x04
|
||||
object | *any value* | document | 0x03
|
||||
binary | *any value* | binary | 0x05
|
||||
|
||||
@warning The mapping is **incomplete**, since only JSON-objects (and things
|
||||
contained therein) can be serialized to BSON.
|
||||
@@ -6938,7 +7449,11 @@ class basic_json
|
||||
Negative integer | number_integer | 0x39
|
||||
Negative integer | number_integer | 0x3A
|
||||
Negative integer | number_integer | 0x3B
|
||||
Negative integer | number_integer | 0x40..0x57
|
||||
Byte string | binary | 0x40..0x57
|
||||
Byte string | binary | 0x58
|
||||
Byte string | binary | 0x59
|
||||
Byte string | binary | 0x5A
|
||||
Byte string | binary | 0x5B
|
||||
UTF-8 string | string | 0x60..0x77
|
||||
UTF-8 string | string | 0x78
|
||||
UTF-8 string | string | 0x79
|
||||
@@ -6967,7 +7482,6 @@ class basic_json
|
||||
@warning The mapping is **incomplete** in the sense that not all CBOR
|
||||
types can be converted to a JSON value. The following CBOR types
|
||||
are not supported and will yield parse errors (parse_error.112):
|
||||
- byte strings (0x40..0x5F)
|
||||
- date/time (0xC0..0xC1)
|
||||
- bignum (0xC2..0xC3)
|
||||
- decimal fraction (0xC4)
|
||||
@@ -7091,15 +7605,19 @@ class basic_json
|
||||
array 32 | array | 0xDD
|
||||
map 16 | object | 0xDE
|
||||
map 32 | object | 0xDF
|
||||
bin 8 | binary | 0xC4
|
||||
bin 16 | binary | 0xC5
|
||||
bin 32 | binary | 0xC6
|
||||
ext 8 | binary | 0xC7
|
||||
ext 16 | binary | 0xC8
|
||||
ext 32 | binary | 0xC9
|
||||
fixext 1 | binary | 0xD4
|
||||
fixext 2 | binary | 0xD5
|
||||
fixext 4 | binary | 0xD6
|
||||
fixext 8 | binary | 0xD7
|
||||
fixext 16 | binary | 0xD8
|
||||
negative fixint | number_integer | 0xE0-0xFF
|
||||
|
||||
@warning The mapping is **incomplete** in the sense that not all
|
||||
MessagePack types can be converted to a JSON value. The following
|
||||
MessagePack types are not supported and will yield parse errors:
|
||||
- bin 8 - bin 32 (0xC4..0xC6)
|
||||
- ext 8 - ext 32 (0xC7..0xC9)
|
||||
- fixext 1 - fixext 16 (0xD4..0xD8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
|
||||
@@ -8018,7 +8536,7 @@ class basic_json
|
||||
result.push_back(
|
||||
{
|
||||
{"op", "add"},
|
||||
{"path", path + "/" + std::to_string(i)},
|
||||
{"path", path + "/-"},
|
||||
{"value", target[i]}
|
||||
});
|
||||
++i;
|
||||
|
Reference in New Issue
Block a user