mirror of
https://github.com/nlohmann/json.git
synced 2024-07-04 21:36:57 +02:00
commit
1300d2e4c3
6
.github/workflows/windows.yml
vendored
6
.github/workflows/windows.yml
vendored
|
@ -43,7 +43,7 @@ jobs:
|
||||||
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
||||||
if: matrix.build_type == 'Release' && matrix.architecture != 'x64'
|
if: matrix.build_type == 'Release' && matrix.architecture != 'x64'
|
||||||
- name: cmake
|
- name: cmake
|
||||||
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 15 2017" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" -DCMAKE_CXX_FLAGS="/W4 /WX"
|
||||||
if: matrix.build_type == 'Debug'
|
if: matrix.build_type == 'Debug'
|
||||||
- name: build
|
- name: build
|
||||||
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
|
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
|
||||||
|
@ -75,7 +75,7 @@ jobs:
|
||||||
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/W4 /WX"
|
||||||
if: matrix.build_type == 'Release'
|
if: matrix.build_type == 'Release'
|
||||||
- name: cmake
|
- name: cmake
|
||||||
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_CXX_FLAGS="/W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 16 2019" -A ${{ matrix.architecture }} -DJSON_BuildTests=On -DJSON_FastTests=ON -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000" -DCMAKE_CXX_FLAGS="/W4 /WX"
|
||||||
if: matrix.build_type == 'Debug'
|
if: matrix.build_type == 'Debug'
|
||||||
- name: build
|
- name: build
|
||||||
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
|
run: cmake --build build --config ${{ matrix.build_type }} --parallel 10
|
||||||
|
@ -88,7 +88,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- name: cmake
|
- name: cmake
|
||||||
run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX"
|
run: cmake -S . -B build -G "Visual Studio 16 2019" -DJSON_BuildTests=On -DCMAKE_CXX_FLAGS="/permissive- /std:c++latest /utf-8 /W4 /WX" -DCMAKE_EXE_LINKER_FLAGS="/STACK:4000000"
|
||||||
- name: build
|
- name: build
|
||||||
run: cmake --build build --config Release --parallel 10
|
run: cmake --build build --config Release --parallel 10
|
||||||
- name: test
|
- name: test
|
||||||
|
|
|
@ -64,4 +64,4 @@ type `#!cpp binary_t*` must be dereferenced.
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.8.0.
|
- Added in version 3.8.0. Changed type of subtype to `std::uint64_t` in version 3.9.2.
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
enum class cbor_tag_handler_t
|
enum class cbor_tag_handler_t
|
||||||
{
|
{
|
||||||
error,
|
error,
|
||||||
ignore
|
ignore,
|
||||||
|
store
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -16,6 +17,9 @@ error
|
||||||
ignore
|
ignore
|
||||||
: ignore tags
|
: ignore tags
|
||||||
|
|
||||||
|
store
|
||||||
|
: store tagged values as binary container with subtype (for bytes 0xd8..0xdb)
|
||||||
|
|
||||||
## Version history
|
## Version history
|
||||||
|
|
||||||
- Added in version 3.9.0.
|
- Added in version 3.9.0. Added value `store` in 3.9.2.
|
||||||
|
|
|
@ -55,6 +55,8 @@ binary | *size*: 256..65535 | byte string (2 by
|
||||||
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
||||||
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
||||||
|
|
||||||
|
Binary values with subtype are mapped to tagged values (0xD8..0xDB) depending on the subtype, followed by a byte string,
|
||||||
|
see "binary" cells in the table above.
|
||||||
|
|
||||||
!!! success "Complete mapping"
|
!!! success "Complete mapping"
|
||||||
|
|
||||||
|
@ -162,7 +164,7 @@ Double-Precision Float | number_float | 0xFB
|
||||||
|
|
||||||
!!! warning "Tagged items"
|
!!! warning "Tagged items"
|
||||||
|
|
||||||
Tagged items will throw a parse error by default. However, they can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`.
|
Tagged items will throw a parse error by default. They can be ignored by passing `cbor_tag_handler_t::ignore` to function `from_cbor`. They can be stored by passing `cbor_tag_handler_t::store` to function `from_cbor`.
|
||||||
|
|
||||||
??? example
|
??? example
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ to efficiently encode JSON values to byte vectors and to decode such vectors.
|
||||||
| Format | Binary values | Binary subtypes |
|
| Format | Binary values | Binary subtypes |
|
||||||
| ----------- | ------------- | --------------- |
|
| ----------- | ------------- | --------------- |
|
||||||
| BSON | supported | supported |
|
| BSON | supported | supported |
|
||||||
| CBOR | supported | not supported |
|
| CBOR | supported | supported |
|
||||||
| MessagePack | supported | supported |
|
| MessagePack | supported | supported |
|
||||||
| UBJSON | not supported | not supported |
|
| UBJSON | not supported | not supported |
|
||||||
|
|
||||||
|
|
|
@ -9,10 +9,10 @@ JSON itself does not have a binary value. As such, binary values are an extensio
|
||||||
```plantuml
|
```plantuml
|
||||||
class json::binary_t {
|
class json::binary_t {
|
||||||
-- setters --
|
-- setters --
|
||||||
+void set_subtype(std::uint8_t subtype)
|
+void set_subtype(std::uint64_t subtype)
|
||||||
+void clear_subtype()
|
+void clear_subtype()
|
||||||
-- getters --
|
-- getters --
|
||||||
+std::uint8_t subtype() const
|
+std::uint64_t subtype() const
|
||||||
+bool has_subtype() const
|
+bool has_subtype() const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ j.get_binary().has_subtype(); // returns true
|
||||||
j.get_binary().size(); // returns 4
|
j.get_binary().size(); // returns 4
|
||||||
```
|
```
|
||||||
|
|
||||||
For convencience, binary JSON values can be constructed via `json::binary`:
|
For convenience, binary JSON values can be constructed via `json::binary`:
|
||||||
|
|
||||||
```cpp
|
```cpp
|
||||||
auto j2 = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 23);
|
auto j2 = json::binary({0xCA, 0xFE, 0xBA, 0xBE}, 23);
|
||||||
|
@ -76,6 +76,7 @@ auto j3 = json::binary({0xCA, 0xFE, 0xBA, 0xBE});
|
||||||
|
|
||||||
j2 == j; // returns true
|
j2 == j; // returns true
|
||||||
j3.get_binary().has_subtype(); // returns false
|
j3.get_binary().has_subtype(); // returns false
|
||||||
|
j3.get_binary().subtype(); // returns std::uint64_t(-1) as j3 has no subtype
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,7 +185,7 @@ JSON does not have a binary type, and this library does not introduce a new type
|
||||||
0xCA 0xFE 0xBA 0xBE // content
|
0xCA 0xFE 0xBA 0xBE // content
|
||||||
```
|
```
|
||||||
|
|
||||||
Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless `json::cbor_tag_handler_t::ignore` is passed to `json::from_cbor`.
|
Note that the subtype is serialized as tag. However, parsing tagged values yield a parse error unless `json::cbor_tag_handler_t::ignore` or `json::cbor_tag_handler_t::store` is passed to `json::from_cbor`.
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t, uint64_t
|
||||||
#include <tuple> // tie
|
#include <tuple> // tie
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ order to override the binary type.
|
||||||
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
|
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
|
||||||
default)
|
default)
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.9.2.
|
||||||
*/
|
*/
|
||||||
template<typename BinaryType>
|
template<typename BinaryType>
|
||||||
class byte_container_with_subtype : public BinaryType
|
class byte_container_with_subtype : public BinaryType
|
||||||
|
@ -26,6 +26,8 @@ class byte_container_with_subtype : public BinaryType
|
||||||
public:
|
public:
|
||||||
/// the type of the underlying container
|
/// the type of the underlying container
|
||||||
using container_type = BinaryType;
|
using container_type = BinaryType;
|
||||||
|
/// the type of the subtype
|
||||||
|
using subtype_type = std::uint64_t;
|
||||||
|
|
||||||
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
||||||
: container_type()
|
: container_type()
|
||||||
|
@ -39,13 +41,13 @@ class byte_container_with_subtype : public BinaryType
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype_) noexcept(noexcept(container_type(b)))
|
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
|
||||||
: container_type(b)
|
: container_type(b)
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype_) noexcept(noexcept(container_type(std::move(b))))
|
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
|
@ -80,7 +82,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0
|
||||||
*/
|
*/
|
||||||
void set_subtype(std::uint8_t subtype_) noexcept
|
void set_subtype(subtype_type subtype_) noexcept
|
||||||
{
|
{
|
||||||
m_subtype = subtype_;
|
m_subtype = subtype_;
|
||||||
m_has_subtype = true;
|
m_has_subtype = true;
|
||||||
|
@ -90,7 +92,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
@brief return the binary subtype
|
@brief return the binary subtype
|
||||||
|
|
||||||
Returns the numerical subtype of the value if it has a subtype. If it does
|
Returns the numerical subtype of the value if it has a subtype. If it does
|
||||||
not have a subtype, this function will return size_t(-1) as a sentinel
|
not have a subtype, this function will return subtype_type(-1) as a sentinel
|
||||||
value.
|
value.
|
||||||
|
|
||||||
@return the numerical subtype of the binary value
|
@return the numerical subtype of the binary value
|
||||||
|
@ -105,11 +107,12 @@ class byte_container_with_subtype : public BinaryType
|
||||||
@sa see @ref has_subtype() -- returns whether or not the binary value has a
|
@sa see @ref has_subtype() -- returns whether or not the binary value has a
|
||||||
subtype
|
subtype
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0; fixed return value to properly return
|
||||||
|
subtype_type(-1) as documented in version 3.9.2
|
||||||
*/
|
*/
|
||||||
constexpr std::uint8_t subtype() const noexcept
|
constexpr subtype_type subtype() const noexcept
|
||||||
{
|
{
|
||||||
return m_subtype;
|
return m_has_subtype ? m_subtype : subtype_type(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -159,7 +162,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_subtype = 0;
|
subtype_type m_subtype = 0;
|
||||||
bool m_has_subtype = false;
|
bool m_has_subtype = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -103,7 +103,7 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
auto seed = combine(type, j.get_binary().size());
|
auto seed = combine(type, j.get_binary().size());
|
||||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, j.get_binary().subtype());
|
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
|
||||||
for (const auto byte : j.get_binary())
|
for (const auto byte : j.get_binary())
|
||||||
{
|
{
|
||||||
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
||||||
|
|
|
@ -30,8 +30,9 @@ namespace detail
|
||||||
/// how to treat CBOR tags
|
/// how to treat CBOR tags
|
||||||
enum class cbor_tag_handler_t
|
enum class cbor_tag_handler_t
|
||||||
{
|
{
|
||||||
error, ///< throw a parse_error exception in case of a tag
|
error, ///< throw a parse_error exception in case of a tag
|
||||||
ignore ///< ignore tags
|
ignore, ///< ignore tags
|
||||||
|
store ///< store tags as binary type
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -723,30 +724,31 @@ class binary_reader
|
||||||
|
|
||||||
case cbor_tag_handler_t::ignore:
|
case cbor_tag_handler_t::ignore:
|
||||||
{
|
{
|
||||||
|
// ignore binary subtype
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
case 0xD8:
|
case 0xD8:
|
||||||
{
|
{
|
||||||
std::uint8_t len{};
|
std::uint8_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
{
|
{
|
||||||
std::uint16_t len{};
|
std::uint16_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xDA:
|
case 0xDA:
|
||||||
{
|
{
|
||||||
std::uint32_t len{};
|
std::uint32_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xDB:
|
case 0xDB:
|
||||||
{
|
{
|
||||||
std::uint64_t len{};
|
std::uint64_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -755,6 +757,47 @@ class binary_reader
|
||||||
return parse_cbor_internal(true, tag_handler);
|
return parse_cbor_internal(true, tag_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case cbor_tag_handler_t::store:
|
||||||
|
{
|
||||||
|
binary_t b;
|
||||||
|
// use binary subtype and store in binary container
|
||||||
|
switch (current)
|
||||||
|
{
|
||||||
|
case 0xD8:
|
||||||
|
{
|
||||||
|
std::uint8_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD9:
|
||||||
|
{
|
||||||
|
std::uint16_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xDA:
|
||||||
|
{
|
||||||
|
std::uint32_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xDB:
|
||||||
|
{
|
||||||
|
std::uint64_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return parse_cbor_internal(true, tag_handler);
|
||||||
|
}
|
||||||
|
get();
|
||||||
|
return get_cbor_binary(b) && sax->binary(b);
|
||||||
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace detail
|
||||||
// parser //
|
// parser //
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
enum class parse_event_t : uint8_t
|
enum class parse_event_t : std::uint8_t
|
||||||
{
|
{
|
||||||
/// the parser read `{` and started to process a JSON object
|
/// the parser read `{` and started to process a JSON object
|
||||||
object_start,
|
object_start,
|
||||||
|
|
|
@ -291,8 +291,26 @@ class binary_writer
|
||||||
{
|
{
|
||||||
if (j.m_value.binary->has_subtype())
|
if (j.m_value.binary->has_subtype())
|
||||||
{
|
{
|
||||||
write_number(static_cast<std::uint8_t>(0xd8));
|
if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
write_number(j.m_value.binary->subtype());
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xd8));
|
||||||
|
write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xd9));
|
||||||
|
write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xda));
|
||||||
|
write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xdb));
|
||||||
|
write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 1: write control byte and the binary array size
|
// step 1: write control byte and the binary array size
|
||||||
|
@ -1109,7 +1127,7 @@ class binary_writer
|
||||||
write_bson_entry_header(name, 0x05);
|
write_bson_entry_header(name, 0x05);
|
||||||
|
|
||||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
|
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
|
||||||
write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
|
write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : std::uint8_t(0x00));
|
||||||
|
|
||||||
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,7 +389,7 @@ class serializer
|
||||||
|
|
||||||
for (std::size_t i = 0; i < s.size(); ++i)
|
for (std::size_t i = 0; i < s.size(); ++i)
|
||||||
{
|
{
|
||||||
const auto byte = static_cast<uint8_t>(s[i]);
|
const auto byte = static_cast<std::uint8_t>(s[i]);
|
||||||
|
|
||||||
switch (decode(state, codepoint, byte))
|
switch (decode(state, codepoint, byte))
|
||||||
{
|
{
|
||||||
|
@ -674,6 +674,7 @@ class serializer
|
||||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||||
*/
|
*/
|
||||||
template < typename NumberType, detail::enable_if_t <
|
template < typename NumberType, detail::enable_if_t <
|
||||||
|
std::is_integral<NumberType>::value ||
|
||||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||||
std::is_same<NumberType, number_integer_t>::value ||
|
std::is_same<NumberType, number_integer_t>::value ||
|
||||||
std::is_same<NumberType, binary_char_t>::value,
|
std::is_same<NumberType, binary_char_t>::value,
|
||||||
|
@ -706,7 +707,7 @@ class serializer
|
||||||
// use a pointer to fill the buffer
|
// use a pointer to fill the buffer
|
||||||
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
|
||||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
|
const bool is_negative = std::is_signed<NumberType>::value && !(x >= 0); // see issue #755
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
|
||||||
unsigned int n_chars{};
|
unsigned int n_chars{};
|
||||||
|
|
|
@ -902,8 +902,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
#### Notes on subtypes
|
#### Notes on subtypes
|
||||||
|
|
||||||
- CBOR
|
- CBOR
|
||||||
- Binary values are represented as byte strings. No subtypes are
|
- Binary values are represented as byte strings. Subtypes are serialized
|
||||||
supported and will be ignored when CBOR is written.
|
as tagged values.
|
||||||
- MessagePack
|
- MessagePack
|
||||||
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
|
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
|
||||||
or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
|
or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
|
||||||
|
@ -1512,7 +1512,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@ref number_float_t, and all convertible number types such as `int`,
|
@ref number_float_t, and all convertible number types such as `int`,
|
||||||
`size_t`, `int64_t`, `float` or `double` can be used.
|
`size_t`, `int64_t`, `float` or `double` can be used.
|
||||||
- **boolean**: @ref boolean_t / `bool` can be used.
|
- **boolean**: @ref boolean_t / `bool` can be used.
|
||||||
- **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
|
- **binary**: @ref binary_t / `std::vector<std::uint8_t>` may be used,
|
||||||
unfortunately because string literals cannot be distinguished from binary
|
unfortunately because string literals cannot be distinguished from binary
|
||||||
character arrays by the C++ type system, all types compatible with `const
|
character arrays by the C++ type system, all types compatible with `const
|
||||||
char*` will be directed to the string constructor instead. This is both
|
char*` will be directed to the string constructor instead. This is both
|
||||||
|
@ -1832,7 +1832,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@since version 3.8.0
|
@since version 3.8.0
|
||||||
*/
|
*/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype)
|
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_type = value_t::binary;
|
res.m_type = value_t::binary;
|
||||||
|
@ -1850,9 +1850,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @copydoc binary(const typename binary_t::container_type&, std::uint8_t)
|
/// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type)
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype)
|
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_type = value_t::binary;
|
res.m_type = value_t::binary;
|
||||||
|
@ -7248,6 +7248,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
||||||
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
||||||
|
|
||||||
|
Binary values with subtype are mapped to tagged values (0xD8..0xDB)
|
||||||
|
depending on the subtype, followed by a byte string, see "binary" cells
|
||||||
|
in the table above.
|
||||||
|
|
||||||
@note The mapping is **complete** in the sense that any JSON value type
|
@note The mapping is **complete** in the sense that any JSON value type
|
||||||
can be converted to a CBOR value.
|
can be converted to a CBOR value.
|
||||||
|
|
||||||
|
@ -7288,16 +7292,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@since version 2.0.9; compact representation of floating-point numbers
|
@since version 2.0.9; compact representation of floating-point numbers
|
||||||
since version 3.8.0
|
since version 3.8.0
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
static std::vector<std::uint8_t> to_cbor(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_cbor(j, result);
|
to_cbor(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_cbor(j);
|
binary_writer<std::uint8_t>(o).write_cbor(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
|
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
|
||||||
|
@ -7383,16 +7387,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
|
|
||||||
@since version 2.0.9
|
@since version 2.0.9
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_msgpack(j, result);
|
to_msgpack(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_msgpack(j);
|
binary_writer<std::uint8_t>(o).write_msgpack(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
|
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
|
||||||
|
@ -7486,19 +7490,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
|
|
||||||
@since version 3.1.0
|
@since version 3.1.0
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_ubjson(const basic_json& j,
|
static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
|
||||||
const bool use_size = false,
|
const bool use_size = false,
|
||||||
const bool use_type = false)
|
const bool use_type = false)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_ubjson(j, result, use_size, use_type);
|
to_ubjson(j, result, use_size, use_type);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
|
static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
|
||||||
const bool use_size = false, const bool use_type = false)
|
const bool use_size = false, const bool use_type = false)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
|
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
|
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
|
||||||
|
@ -7564,9 +7568,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@sa see @ref to_cbor(const basic_json&) for the related CBOR format
|
@sa see @ref to_cbor(const basic_json&) for the related CBOR format
|
||||||
@sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
|
@sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_bson(const basic_json& j)
|
static std::vector<std::uint8_t> to_bson(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_bson(j, result);
|
to_bson(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -7579,13 +7583,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@pre The input `j` shall be an object: `j.is_object() == true`
|
@pre The input `j` shall be an object: `j.is_object() == true`
|
||||||
@sa see @ref to_bson(const basic_json&)
|
@sa see @ref to_bson(const basic_json&)
|
||||||
*/
|
*/
|
||||||
static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_bson(j);
|
binary_writer<std::uint8_t>(o).write_bson(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
|
@copydoc to_bson(const basic_json&, detail::output_adapter<std::uint8_t>)
|
||||||
*/
|
*/
|
||||||
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
|
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
|
||||||
{
|
{
|
||||||
|
|
|
@ -4985,7 +4985,7 @@ struct adl_serializer
|
||||||
// #include <nlohmann/byte_container_with_subtype.hpp>
|
// #include <nlohmann/byte_container_with_subtype.hpp>
|
||||||
|
|
||||||
|
|
||||||
#include <cstdint> // uint8_t
|
#include <cstdint> // uint8_t, uint64_t
|
||||||
#include <tuple> // tie
|
#include <tuple> // tie
|
||||||
#include <utility> // move
|
#include <utility> // move
|
||||||
|
|
||||||
|
@ -5003,7 +5003,7 @@ order to override the binary type.
|
||||||
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
|
@tparam BinaryType container to store bytes (`std::vector<std::uint8_t>` by
|
||||||
default)
|
default)
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0; changed type of subtypes to std::uint64_t in 3.9.2.
|
||||||
*/
|
*/
|
||||||
template<typename BinaryType>
|
template<typename BinaryType>
|
||||||
class byte_container_with_subtype : public BinaryType
|
class byte_container_with_subtype : public BinaryType
|
||||||
|
@ -5011,6 +5011,8 @@ class byte_container_with_subtype : public BinaryType
|
||||||
public:
|
public:
|
||||||
/// the type of the underlying container
|
/// the type of the underlying container
|
||||||
using container_type = BinaryType;
|
using container_type = BinaryType;
|
||||||
|
/// the type of the subtype
|
||||||
|
using subtype_type = std::uint64_t;
|
||||||
|
|
||||||
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
byte_container_with_subtype() noexcept(noexcept(container_type()))
|
||||||
: container_type()
|
: container_type()
|
||||||
|
@ -5024,13 +5026,13 @@ class byte_container_with_subtype : public BinaryType
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
{}
|
{}
|
||||||
|
|
||||||
byte_container_with_subtype(const container_type& b, std::uint8_t subtype_) noexcept(noexcept(container_type(b)))
|
byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
|
||||||
: container_type(b)
|
: container_type(b)
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
byte_container_with_subtype(container_type&& b, std::uint8_t subtype_) noexcept(noexcept(container_type(std::move(b))))
|
byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
|
||||||
: container_type(std::move(b))
|
: container_type(std::move(b))
|
||||||
, m_subtype(subtype_)
|
, m_subtype(subtype_)
|
||||||
, m_has_subtype(true)
|
, m_has_subtype(true)
|
||||||
|
@ -5065,7 +5067,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0
|
||||||
*/
|
*/
|
||||||
void set_subtype(std::uint8_t subtype_) noexcept
|
void set_subtype(subtype_type subtype_) noexcept
|
||||||
{
|
{
|
||||||
m_subtype = subtype_;
|
m_subtype = subtype_;
|
||||||
m_has_subtype = true;
|
m_has_subtype = true;
|
||||||
|
@ -5075,7 +5077,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
@brief return the binary subtype
|
@brief return the binary subtype
|
||||||
|
|
||||||
Returns the numerical subtype of the value if it has a subtype. If it does
|
Returns the numerical subtype of the value if it has a subtype. If it does
|
||||||
not have a subtype, this function will return size_t(-1) as a sentinel
|
not have a subtype, this function will return subtype_type(-1) as a sentinel
|
||||||
value.
|
value.
|
||||||
|
|
||||||
@return the numerical subtype of the binary value
|
@return the numerical subtype of the binary value
|
||||||
|
@ -5090,11 +5092,12 @@ class byte_container_with_subtype : public BinaryType
|
||||||
@sa see @ref has_subtype() -- returns whether or not the binary value has a
|
@sa see @ref has_subtype() -- returns whether or not the binary value has a
|
||||||
subtype
|
subtype
|
||||||
|
|
||||||
@since version 3.8.0
|
@since version 3.8.0; fixed return value to properly return
|
||||||
|
subtype_type(-1) as documented in version 3.9.2
|
||||||
*/
|
*/
|
||||||
constexpr std::uint8_t subtype() const noexcept
|
constexpr subtype_type subtype() const noexcept
|
||||||
{
|
{
|
||||||
return m_subtype;
|
return m_has_subtype ? m_subtype : subtype_type(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -5144,7 +5147,7 @@ class byte_container_with_subtype : public BinaryType
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::uint8_t m_subtype = 0;
|
subtype_type m_subtype = 0;
|
||||||
bool m_has_subtype = false;
|
bool m_has_subtype = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5263,7 +5266,7 @@ std::size_t hash(const BasicJsonType& j)
|
||||||
auto seed = combine(type, j.get_binary().size());
|
auto seed = combine(type, j.get_binary().size());
|
||||||
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
|
||||||
seed = combine(seed, h);
|
seed = combine(seed, h);
|
||||||
seed = combine(seed, j.get_binary().subtype());
|
seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
|
||||||
for (const auto byte : j.get_binary())
|
for (const auto byte : j.get_binary())
|
||||||
{
|
{
|
||||||
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
seed = combine(seed, std::hash<std::uint8_t> {}(byte));
|
||||||
|
@ -8296,8 +8299,9 @@ namespace detail
|
||||||
/// how to treat CBOR tags
|
/// how to treat CBOR tags
|
||||||
enum class cbor_tag_handler_t
|
enum class cbor_tag_handler_t
|
||||||
{
|
{
|
||||||
error, ///< throw a parse_error exception in case of a tag
|
error, ///< throw a parse_error exception in case of a tag
|
||||||
ignore ///< ignore tags
|
ignore, ///< ignore tags
|
||||||
|
store ///< store tags as binary type
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -8989,30 +8993,31 @@ class binary_reader
|
||||||
|
|
||||||
case cbor_tag_handler_t::ignore:
|
case cbor_tag_handler_t::ignore:
|
||||||
{
|
{
|
||||||
|
// ignore binary subtype
|
||||||
switch (current)
|
switch (current)
|
||||||
{
|
{
|
||||||
case 0xD8:
|
case 0xD8:
|
||||||
{
|
{
|
||||||
std::uint8_t len{};
|
std::uint8_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xD9:
|
case 0xD9:
|
||||||
{
|
{
|
||||||
std::uint16_t len{};
|
std::uint16_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xDA:
|
case 0xDA:
|
||||||
{
|
{
|
||||||
std::uint32_t len{};
|
std::uint32_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 0xDB:
|
case 0xDB:
|
||||||
{
|
{
|
||||||
std::uint64_t len{};
|
std::uint64_t subtype_to_ignore{};
|
||||||
get_number(input_format_t::cbor, len);
|
get_number(input_format_t::cbor, subtype_to_ignore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -9021,6 +9026,47 @@ class binary_reader
|
||||||
return parse_cbor_internal(true, tag_handler);
|
return parse_cbor_internal(true, tag_handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case cbor_tag_handler_t::store:
|
||||||
|
{
|
||||||
|
binary_t b;
|
||||||
|
// use binary subtype and store in binary container
|
||||||
|
switch (current)
|
||||||
|
{
|
||||||
|
case 0xD8:
|
||||||
|
{
|
||||||
|
std::uint8_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xD9:
|
||||||
|
{
|
||||||
|
std::uint16_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xDA:
|
||||||
|
{
|
||||||
|
std::uint32_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0xDB:
|
||||||
|
{
|
||||||
|
std::uint64_t subtype{};
|
||||||
|
get_number(input_format_t::cbor, subtype);
|
||||||
|
b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return parse_cbor_internal(true, tag_handler);
|
||||||
|
}
|
||||||
|
get();
|
||||||
|
return get_cbor_binary(b) && sax->binary(b);
|
||||||
|
}
|
||||||
|
|
||||||
default: // LCOV_EXCL_LINE
|
default: // LCOV_EXCL_LINE
|
||||||
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
|
||||||
return false; // LCOV_EXCL_LINE
|
return false; // LCOV_EXCL_LINE
|
||||||
|
@ -10783,7 +10829,7 @@ namespace detail
|
||||||
// parser //
|
// parser //
|
||||||
////////////
|
////////////
|
||||||
|
|
||||||
enum class parse_event_t : uint8_t
|
enum class parse_event_t : std::uint8_t
|
||||||
{
|
{
|
||||||
/// the parser read `{` and started to process a JSON object
|
/// the parser read `{` and started to process a JSON object
|
||||||
object_start,
|
object_start,
|
||||||
|
@ -13792,8 +13838,26 @@ class binary_writer
|
||||||
{
|
{
|
||||||
if (j.m_value.binary->has_subtype())
|
if (j.m_value.binary->has_subtype())
|
||||||
{
|
{
|
||||||
write_number(static_cast<std::uint8_t>(0xd8));
|
if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
|
||||||
write_number(j.m_value.binary->subtype());
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xd8));
|
||||||
|
write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xd9));
|
||||||
|
write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xda));
|
||||||
|
write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
|
else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
|
||||||
|
{
|
||||||
|
write_number(static_cast<std::uint8_t>(0xdb));
|
||||||
|
write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// step 1: write control byte and the binary array size
|
// step 1: write control byte and the binary array size
|
||||||
|
@ -14610,7 +14674,7 @@ class binary_writer
|
||||||
write_bson_entry_header(name, 0x05);
|
write_bson_entry_header(name, 0x05);
|
||||||
|
|
||||||
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
|
write_number<std::int32_t, true>(static_cast<std::int32_t>(value.size()));
|
||||||
write_number(value.has_subtype() ? value.subtype() : std::uint8_t(0x00));
|
write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : std::uint8_t(0x00));
|
||||||
|
|
||||||
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
|
||||||
}
|
}
|
||||||
|
@ -16629,7 +16693,7 @@ class serializer
|
||||||
|
|
||||||
for (std::size_t i = 0; i < s.size(); ++i)
|
for (std::size_t i = 0; i < s.size(); ++i)
|
||||||
{
|
{
|
||||||
const auto byte = static_cast<uint8_t>(s[i]);
|
const auto byte = static_cast<std::uint8_t>(s[i]);
|
||||||
|
|
||||||
switch (decode(state, codepoint, byte))
|
switch (decode(state, codepoint, byte))
|
||||||
{
|
{
|
||||||
|
@ -16914,6 +16978,7 @@ class serializer
|
||||||
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
@tparam NumberType either @a number_integer_t or @a number_unsigned_t
|
||||||
*/
|
*/
|
||||||
template < typename NumberType, detail::enable_if_t <
|
template < typename NumberType, detail::enable_if_t <
|
||||||
|
std::is_integral<NumberType>::value ||
|
||||||
std::is_same<NumberType, number_unsigned_t>::value ||
|
std::is_same<NumberType, number_unsigned_t>::value ||
|
||||||
std::is_same<NumberType, number_integer_t>::value ||
|
std::is_same<NumberType, number_integer_t>::value ||
|
||||||
std::is_same<NumberType, binary_char_t>::value,
|
std::is_same<NumberType, binary_char_t>::value,
|
||||||
|
@ -16946,7 +17011,7 @@ class serializer
|
||||||
// use a pointer to fill the buffer
|
// use a pointer to fill the buffer
|
||||||
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
|
||||||
|
|
||||||
const bool is_negative = std::is_same<NumberType, number_integer_t>::value && !(x >= 0); // see issue #755
|
const bool is_negative = std::is_signed<NumberType>::value && !(x >= 0); // see issue #755
|
||||||
number_unsigned_t abs_value;
|
number_unsigned_t abs_value;
|
||||||
|
|
||||||
unsigned int n_chars{};
|
unsigned int n_chars{};
|
||||||
|
@ -18217,8 +18282,8 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
#### Notes on subtypes
|
#### Notes on subtypes
|
||||||
|
|
||||||
- CBOR
|
- CBOR
|
||||||
- Binary values are represented as byte strings. No subtypes are
|
- Binary values are represented as byte strings. Subtypes are serialized
|
||||||
supported and will be ignored when CBOR is written.
|
as tagged values.
|
||||||
- MessagePack
|
- MessagePack
|
||||||
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
|
- If a subtype is given and the binary array contains exactly 1, 2, 4, 8,
|
||||||
or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
|
or 16 elements, the fixext family (fixext1, fixext2, fixext4, fixext8)
|
||||||
|
@ -18827,7 +18892,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@ref number_float_t, and all convertible number types such as `int`,
|
@ref number_float_t, and all convertible number types such as `int`,
|
||||||
`size_t`, `int64_t`, `float` or `double` can be used.
|
`size_t`, `int64_t`, `float` or `double` can be used.
|
||||||
- **boolean**: @ref boolean_t / `bool` can be used.
|
- **boolean**: @ref boolean_t / `bool` can be used.
|
||||||
- **binary**: @ref binary_t / `std::vector<uint8_t>` may be used,
|
- **binary**: @ref binary_t / `std::vector<std::uint8_t>` may be used,
|
||||||
unfortunately because string literals cannot be distinguished from binary
|
unfortunately because string literals cannot be distinguished from binary
|
||||||
character arrays by the C++ type system, all types compatible with `const
|
character arrays by the C++ type system, all types compatible with `const
|
||||||
char*` will be directed to the string constructor instead. This is both
|
char*` will be directed to the string constructor instead. This is both
|
||||||
|
@ -19147,7 +19212,7 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@since version 3.8.0
|
@since version 3.8.0
|
||||||
*/
|
*/
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json binary(const typename binary_t::container_type& init, std::uint8_t subtype)
|
static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_type = value_t::binary;
|
res.m_type = value_t::binary;
|
||||||
|
@ -19165,9 +19230,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @copydoc binary(const typename binary_t::container_type&, std::uint8_t)
|
/// @copydoc binary(const typename binary_t::container_type&, typename binary_t::subtype_type)
|
||||||
JSON_HEDLEY_WARN_UNUSED_RESULT
|
JSON_HEDLEY_WARN_UNUSED_RESULT
|
||||||
static basic_json binary(typename binary_t::container_type&& init, std::uint8_t subtype)
|
static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
|
||||||
{
|
{
|
||||||
auto res = basic_json();
|
auto res = basic_json();
|
||||||
res.m_type = value_t::binary;
|
res.m_type = value_t::binary;
|
||||||
|
@ -24563,6 +24628,10 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
binary | *size*: 65536..4294967295 | byte string (4 bytes follow) | 0x5A
|
||||||
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
binary | *size*: 4294967296..18446744073709551615 | byte string (8 bytes follow) | 0x5B
|
||||||
|
|
||||||
|
Binary values with subtype are mapped to tagged values (0xD8..0xDB)
|
||||||
|
depending on the subtype, followed by a byte string, see "binary" cells
|
||||||
|
in the table above.
|
||||||
|
|
||||||
@note The mapping is **complete** in the sense that any JSON value type
|
@note The mapping is **complete** in the sense that any JSON value type
|
||||||
can be converted to a CBOR value.
|
can be converted to a CBOR value.
|
||||||
|
|
||||||
|
@ -24603,16 +24672,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@since version 2.0.9; compact representation of floating-point numbers
|
@since version 2.0.9; compact representation of floating-point numbers
|
||||||
since version 3.8.0
|
since version 3.8.0
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
static std::vector<std::uint8_t> to_cbor(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_cbor(j, result);
|
to_cbor(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_cbor(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_cbor(j);
|
binary_writer<std::uint8_t>(o).write_cbor(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
|
static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
|
||||||
|
@ -24698,16 +24767,16 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
|
|
||||||
@since version 2.0.9
|
@since version 2.0.9
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_msgpack(j, result);
|
to_msgpack(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_msgpack(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_msgpack(j);
|
binary_writer<std::uint8_t>(o).write_msgpack(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
|
static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
|
||||||
|
@ -24801,19 +24870,19 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
|
|
||||||
@since version 3.1.0
|
@since version 3.1.0
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_ubjson(const basic_json& j,
|
static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
|
||||||
const bool use_size = false,
|
const bool use_size = false,
|
||||||
const bool use_type = false)
|
const bool use_type = false)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_ubjson(j, result, use_size, use_type);
|
to_ubjson(j, result, use_size, use_type);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_ubjson(const basic_json& j, detail::output_adapter<uint8_t> o,
|
static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
|
||||||
const bool use_size = false, const bool use_type = false)
|
const bool use_size = false, const bool use_type = false)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_ubjson(j, use_size, use_type);
|
binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
|
static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
|
||||||
|
@ -24879,9 +24948,9 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@sa see @ref to_cbor(const basic_json&) for the related CBOR format
|
@sa see @ref to_cbor(const basic_json&) for the related CBOR format
|
||||||
@sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
|
@sa see @ref to_msgpack(const basic_json&) for the related MessagePack format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_bson(const basic_json& j)
|
static std::vector<std::uint8_t> to_bson(const basic_json& j)
|
||||||
{
|
{
|
||||||
std::vector<uint8_t> result;
|
std::vector<std::uint8_t> result;
|
||||||
to_bson(j, result);
|
to_bson(j, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -24894,13 +24963,13 @@ class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-spec
|
||||||
@pre The input `j` shall be an object: `j.is_object() == true`
|
@pre The input `j` shall be an object: `j.is_object() == true`
|
||||||
@sa see @ref to_bson(const basic_json&)
|
@sa see @ref to_bson(const basic_json&)
|
||||||
*/
|
*/
|
||||||
static void to_bson(const basic_json& j, detail::output_adapter<uint8_t> o)
|
static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
|
||||||
{
|
{
|
||||||
binary_writer<uint8_t>(o).write_bson(j);
|
binary_writer<std::uint8_t>(o).write_bson(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@copydoc to_bson(const basic_json&, detail::output_adapter<uint8_t>)
|
@copydoc to_bson(const basic_json&, detail::output_adapter<std::uint8_t>)
|
||||||
*/
|
*/
|
||||||
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
|
static void to_bson(const basic_json& j, detail::output_adapter<char> o)
|
||||||
{
|
{
|
||||||
|
|
97
test/src/unit-byte_container_with_subtype.cpp
Normal file
97
test/src/unit-byte_container_with_subtype.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
__ _____ _____ _____
|
||||||
|
__| | __| | | | JSON for Modern C++ (test suite)
|
||||||
|
| | |__ | | | | | | version 3.9.1
|
||||||
|
|_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||||
|
|
||||||
|
Licensed under the MIT License <http://opensource.org/licenses/MIT>.
|
||||||
|
SPDX-License-Identifier: MIT
|
||||||
|
Copyright (c) 2013-2019 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;
|
||||||
|
|
||||||
|
TEST_CASE("byte_container_with_subtype")
|
||||||
|
{
|
||||||
|
using subtype_type = nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>>::subtype_type;
|
||||||
|
|
||||||
|
SECTION("empty container")
|
||||||
|
{
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container;
|
||||||
|
|
||||||
|
CHECK(!container.has_subtype());
|
||||||
|
CHECK(container.subtype() == subtype_type(-1));
|
||||||
|
|
||||||
|
container.clear_subtype();
|
||||||
|
CHECK(!container.has_subtype());
|
||||||
|
CHECK(container.subtype() == subtype_type(-1));
|
||||||
|
|
||||||
|
container.set_subtype(42);
|
||||||
|
CHECK(container.has_subtype());
|
||||||
|
CHECK(container.subtype() == 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("subtyped container")
|
||||||
|
{
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container({}, 42);
|
||||||
|
CHECK(container.has_subtype());
|
||||||
|
CHECK(container.subtype() == 42);
|
||||||
|
|
||||||
|
container.clear_subtype();
|
||||||
|
CHECK(!container.has_subtype());
|
||||||
|
CHECK(container.subtype() == subtype_type(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("comparisons")
|
||||||
|
{
|
||||||
|
std::vector<std::uint8_t> bytes = {{0xCA, 0xFE, 0xBA, 0xBE}};
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container1;
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container2({}, 42);
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container3(bytes);
|
||||||
|
nlohmann::byte_container_with_subtype<std::vector<std::uint8_t>> container4(bytes, 42);
|
||||||
|
|
||||||
|
CHECK(container1 == container1);
|
||||||
|
CHECK(container1 != container2);
|
||||||
|
CHECK(container1 != container3);
|
||||||
|
CHECK(container1 != container4);
|
||||||
|
CHECK(container2 != container1);
|
||||||
|
CHECK(container2 == container2);
|
||||||
|
CHECK(container2 != container3);
|
||||||
|
CHECK(container2 != container4);
|
||||||
|
CHECK(container3 != container1);
|
||||||
|
CHECK(container3 != container2);
|
||||||
|
CHECK(container3 == container3);
|
||||||
|
CHECK(container3 != container4);
|
||||||
|
CHECK(container4 != container1);
|
||||||
|
CHECK(container4 != container2);
|
||||||
|
CHECK(container4 != container3);
|
||||||
|
CHECK(container4 == container4);
|
||||||
|
|
||||||
|
container3.clear();
|
||||||
|
container4.clear();
|
||||||
|
|
||||||
|
CHECK(container1 == container3);
|
||||||
|
CHECK(container2 == container4);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2486,7 +2486,22 @@ TEST_CASE("examples from RFC 7049 Appendix A")
|
||||||
auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out");
|
auto expected = utils::read_binary_file(TEST_DATA_DIRECTORY "/binary_data/cbor_binary.out");
|
||||||
CHECK(j == json::binary(expected));
|
CHECK(j == json::binary(expected));
|
||||||
|
|
||||||
|
// 0xd8
|
||||||
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)) == std::vector<uint8_t> {0xd8, 0x42, 0x40});
|
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)) == std::vector<uint8_t> {0xd8, 0x42, 0x40});
|
||||||
|
CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
|
||||||
|
CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 0x42)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 0x42);
|
||||||
|
// 0xd9
|
||||||
|
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)) == std::vector<uint8_t> {0xd9, 0x03, 0xe8, 0x40});
|
||||||
|
CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
|
||||||
|
CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 1000)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 1000);
|
||||||
|
// 0xda
|
||||||
|
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)) == std::vector<uint8_t> {0xda, 0x00, 0x06, 0x03, 0xe8, 0x40});
|
||||||
|
CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
|
||||||
|
CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 394216)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 394216);
|
||||||
|
// 0xdb
|
||||||
|
CHECK(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)) == std::vector<uint8_t> {0xdb, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x40});
|
||||||
|
CHECK(!json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)), true, true, json::cbor_tag_handler_t::ignore).get_binary().has_subtype());
|
||||||
|
CHECK(json::from_cbor(json::to_cbor(json::binary(std::vector<uint8_t> {}, 8589934590)), true, true, json::cbor_tag_handler_t::store).get_binary().subtype() == 8589934590);
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("arrays")
|
SECTION("arrays")
|
||||||
|
@ -2545,6 +2560,8 @@ TEST_CASE("Tagged values")
|
||||||
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
|
0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
|
CAPTURE(b);
|
||||||
|
|
||||||
// add tag to value
|
// add tag to value
|
||||||
auto v_tagged = v;
|
auto v_tagged = v;
|
||||||
v_tagged.insert(v_tagged.begin(), b);
|
v_tagged.insert(v_tagged.begin(), b);
|
||||||
|
@ -2557,6 +2574,9 @@ TEST_CASE("Tagged values")
|
||||||
// check that parsing succeeds and gets original value in ignore mode
|
// check that parsing succeeds and gets original value in ignore mode
|
||||||
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
auto j_tagged = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::ignore);
|
||||||
CHECK(j_tagged == j);
|
CHECK(j_tagged == j);
|
||||||
|
|
||||||
|
auto j_tagged_stored = json::from_cbor(v_tagged, true, true, json::cbor_tag_handler_t::store);
|
||||||
|
CHECK(j_tagged_stored == j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue