📝 clean up and added documentation for #358
This commit is contained in:
parent
fdce38fa79
commit
dc6fc3e079
15 changed files with 665 additions and 114 deletions
18
doc/examples/from_cbor.cpp
Normal file
18
doc/examples/from_cbor.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create byte vector
|
||||||
|
std::vector<uint8_t> v = {0xa2, 0x67, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
|
||||||
|
0x74, 0xf5, 0x66, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||||
|
0x61, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
// deserialize it with CBOR
|
||||||
|
json j = json::from_cbor(v);
|
||||||
|
|
||||||
|
// print the deserialized JSON value
|
||||||
|
std::cout << std::setw(2) << j << std::endl;
|
||||||
|
}
|
1
doc/examples/from_cbor.link
Normal file
1
doc/examples/from_cbor.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/TDPaxmQ7PsvfWxrs"><b>online</b></a>
|
4
doc/examples/from_cbor.output
Normal file
4
doc/examples/from_cbor.output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"compact": true,
|
||||||
|
"schema": 0
|
||||||
|
}
|
18
doc/examples/from_msgpack.cpp
Normal file
18
doc/examples/from_msgpack.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create byte vector
|
||||||
|
std::vector<uint8_t> v = {0x82, 0xa7, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x63,
|
||||||
|
0x74, 0xc3, 0xa6, 0x73, 0x63, 0x68, 0x65, 0x6d,
|
||||||
|
0x61, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
// deserialize it with MessagePack
|
||||||
|
json j = json::from_msgpack(v);
|
||||||
|
|
||||||
|
// print the deserialized JSON value
|
||||||
|
std::cout << std::setw(2) << j << std::endl;
|
||||||
|
}
|
1
doc/examples/from_msgpack.link
Normal file
1
doc/examples/from_msgpack.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/7vRGmLdVcYM7POhE"><b>online</b></a>
|
4
doc/examples/from_msgpack.output
Normal file
4
doc/examples/from_msgpack.output
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"compact": true,
|
||||||
|
"schema": 0
|
||||||
|
}
|
19
doc/examples/to_cbor.cpp
Normal file
19
doc/examples/to_cbor.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON value
|
||||||
|
json j = R"({"compact": true, "schema": 0})"_json;
|
||||||
|
|
||||||
|
// serialize it to CBOR
|
||||||
|
std::vector<uint8_t> v = json::to_cbor(j);
|
||||||
|
|
||||||
|
// print the vector content
|
||||||
|
for (auto& byte : v)
|
||||||
|
{
|
||||||
|
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
1
doc/examples/to_cbor.link
Normal file
1
doc/examples/to_cbor.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/UaDbrgZ8OPWaShY8"><b>online</b></a>
|
1
doc/examples/to_cbor.output
Normal file
1
doc/examples/to_cbor.output
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0xa2 0x67 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xf5 0x66 0x73 0x63 0x68 0x65 0x6d 0x61 0x00
|
19
doc/examples/to_msgpack.cpp
Normal file
19
doc/examples/to_msgpack.cpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#include <json.hpp>
|
||||||
|
|
||||||
|
using json = nlohmann::json;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
// create a JSON value
|
||||||
|
json j = R"({"compact": true, "schema": 0})"_json;
|
||||||
|
|
||||||
|
// serialize it to MessagePack
|
||||||
|
std::vector<uint8_t> v = json::to_msgpack(j);
|
||||||
|
|
||||||
|
// print the vector content
|
||||||
|
for (auto& byte : v)
|
||||||
|
{
|
||||||
|
std::cout << "0x" << std::hex << std::setw(2) << std::setfill('0') << (int)byte << " ";
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
1
doc/examples/to_msgpack.link
Normal file
1
doc/examples/to_msgpack.link
Normal file
|
@ -0,0 +1 @@
|
||||||
|
<a target="_blank" href="http://melpon.org/wandbox/permlink/jvaU8GEfAusb5dKf"><b>online</b></a>
|
1
doc/examples/to_msgpack.output
Normal file
1
doc/examples/to_msgpack.output
Normal file
|
@ -0,0 +1 @@
|
||||||
|
0x82 0xa7 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xc3 0xa6 0x73 0x63 0x68 0x65 0x6d 0x61 0x00
|
266
src/json.hpp
266
src/json.hpp
|
@ -6312,6 +6312,16 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
This is a straightforward implementation of the MessagePack specification.
|
||||||
|
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@param[in,out] v byte vector to write the serialization to
|
||||||
|
|
||||||
|
@sa https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||||
|
*/
|
||||||
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
|
@ -6332,34 +6342,72 @@ class basic_json
|
||||||
|
|
||||||
case value_t::number_integer:
|
case value_t::number_integer:
|
||||||
{
|
{
|
||||||
if (j.m_value.number_integer >= -32 and j.m_value.number_integer < 128)
|
if (j.m_value.number_integer >= 0)
|
||||||
{
|
{
|
||||||
// negative fixnum and positive fixnum
|
// MessagePack does not differentiate between positive
|
||||||
add_to_vector(v, 1, j.m_value.number_integer);
|
// signed integers and unsigned integers. Therefore, we used
|
||||||
|
// the code from the value_t::number_unsigned case here.
|
||||||
|
if (j.m_value.number_unsigned < 128)
|
||||||
|
{
|
||||||
|
// positive fixnum
|
||||||
|
add_to_vector(v, 1, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT8_MAX)
|
||||||
|
{
|
||||||
|
// uint 8
|
||||||
|
v.push_back(0xcc);
|
||||||
|
add_to_vector(v, 1, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
// uint 16
|
||||||
|
v.push_back(0xcd);
|
||||||
|
add_to_vector(v, 2, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
// uint 32
|
||||||
|
v.push_back(0xce);
|
||||||
|
add_to_vector(v, 4, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT64_MAX)
|
||||||
|
{
|
||||||
|
// uint 64
|
||||||
|
v.push_back(0xcf);
|
||||||
|
add_to_vector(v, 8, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
else
|
||||||
{
|
{
|
||||||
// int 8
|
if (j.m_value.number_integer >= -32)
|
||||||
v.push_back(0xd0);
|
{
|
||||||
add_to_vector(v, 1, j.m_value.number_integer);
|
// negative fixnum
|
||||||
}
|
add_to_vector(v, 1, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
||||||
// int 16
|
{
|
||||||
v.push_back(0xd1);
|
// int 8
|
||||||
add_to_vector(v, 2, j.m_value.number_integer);
|
v.push_back(0xd0);
|
||||||
}
|
add_to_vector(v, 1, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
||||||
// int 32
|
{
|
||||||
v.push_back(0xd2);
|
// int 16
|
||||||
add_to_vector(v, 4, j.m_value.number_integer);
|
v.push_back(0xd1);
|
||||||
}
|
add_to_vector(v, 2, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
||||||
// int 64
|
{
|
||||||
v.push_back(0xd3);
|
// int 32
|
||||||
add_to_vector(v, 8, j.m_value.number_integer);
|
v.push_back(0xd2);
|
||||||
|
add_to_vector(v, 4, j.m_value.number_integer);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
||||||
|
{
|
||||||
|
// int 64
|
||||||
|
v.push_back(0xd3);
|
||||||
|
add_to_vector(v, 8, j.m_value.number_integer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6509,6 +6557,16 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a CBOR serialization of a given JSON value
|
||||||
|
|
||||||
|
This is a straightforward implementation of the CBOR specification.
|
||||||
|
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@param[in,out] v byte vector to write the serialization to
|
||||||
|
|
||||||
|
@sa https://tools.ietf.org/html/rfc7049
|
||||||
|
*/
|
||||||
static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
|
static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
|
@ -6566,7 +6624,7 @@ class basic_json
|
||||||
// The conversions below encode the sign in the first byte,
|
// The conversions below encode the sign in the first byte,
|
||||||
// and the value is converted to a positive number.
|
// and the value is converted to a positive number.
|
||||||
const auto positive_number = -1 - j.m_value.number_integer;
|
const auto positive_number = -1 - j.m_value.number_integer;
|
||||||
if (j.m_value.number_integer <= -1 and j.m_value.number_integer >= -24)
|
if (j.m_value.number_integer >= -24)
|
||||||
{
|
{
|
||||||
v.push_back(static_cast<uint8_t>(0x20 + positive_number));
|
v.push_back(static_cast<uint8_t>(0x20 + positive_number));
|
||||||
}
|
}
|
||||||
|
@ -6648,32 +6706,30 @@ class basic_json
|
||||||
const auto N = j.m_value.string->size();
|
const auto N = j.m_value.string->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
v.push_back(0x60 + N);
|
v.push_back(0x60 + N); // 1 byte for string + size
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0x78);
|
v.push_back(0x78); // one-byte uint8_t for N
|
||||||
// one-byte uint8_t for N
|
|
||||||
add_to_vector(v, 1, N);
|
add_to_vector(v, 1, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x79);
|
v.push_back(0x79); // two-byte uint16_t for N
|
||||||
// two-byte uint16_t for N
|
|
||||||
add_to_vector(v, 2, N);
|
add_to_vector(v, 2, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x7a);
|
v.push_back(0x7a); // four-byte uint32_t for N
|
||||||
// four-byte uint32_t for N
|
|
||||||
add_to_vector(v, 4, N);
|
add_to_vector(v, 4, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x7b);
|
v.push_back(0x7b); // eight-byte uint64_t for N
|
||||||
// eight-byte uint64_t for N
|
|
||||||
add_to_vector(v, 8, N);
|
add_to_vector(v, 8, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append string
|
// append string
|
||||||
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
||||||
|
@ -6686,33 +6742,30 @@ class basic_json
|
||||||
const auto N = j.m_value.array->size();
|
const auto N = j.m_value.array->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
// 1 byte for array + size
|
v.push_back(0x80 + N); // 1 byte for array + size
|
||||||
v.push_back(0x80 + N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0x98);
|
v.push_back(0x98); // one-byte uint8_t for N
|
||||||
// one-byte uint8_t for N
|
|
||||||
add_to_vector(v, 1, N);
|
add_to_vector(v, 1, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x99);
|
v.push_back(0x99); // two-byte uint16_t for N
|
||||||
// two-byte uint16_t for N
|
|
||||||
add_to_vector(v, 2, N);
|
add_to_vector(v, 2, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x9a);
|
v.push_back(0x9a); // four-byte uint32_t for N
|
||||||
// four-byte uint32_t for N
|
|
||||||
add_to_vector(v, 4, N);
|
add_to_vector(v, 4, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x9b);
|
v.push_back(0x9b); // eight-byte uint64_t for N
|
||||||
// eight-byte uint64_t for N
|
|
||||||
add_to_vector(v, 8, N);
|
add_to_vector(v, 8, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append each element
|
// append each element
|
||||||
for (const auto& el : *j.m_value.array)
|
for (const auto& el : *j.m_value.array)
|
||||||
|
@ -6727,33 +6780,30 @@ class basic_json
|
||||||
const auto N = j.m_value.object->size();
|
const auto N = j.m_value.object->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
// 1 byte for object + size
|
v.push_back(0xa0 + N); // 1 byte for object + size
|
||||||
v.push_back(0xa0 + N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0xb8);
|
v.push_back(0xb8);
|
||||||
// one-byte uint8_t for N
|
add_to_vector(v, 1, N); // one-byte uint8_t for N
|
||||||
add_to_vector(v, 1, N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xb9);
|
v.push_back(0xb9);
|
||||||
// two-byte uint16_t for N
|
add_to_vector(v, 2, N); // two-byte uint16_t for N
|
||||||
add_to_vector(v, 2, N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xba);
|
v.push_back(0xba);
|
||||||
// four-byte uint32_t for N
|
add_to_vector(v, 4, N); // four-byte uint32_t for N
|
||||||
add_to_vector(v, 4, N);
|
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xbb);
|
v.push_back(0xbb);
|
||||||
// eight-byte uint64_t for N
|
add_to_vector(v, 8, N); // eight-byte uint64_t for N
|
||||||
add_to_vector(v, 8, N);
|
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append each element
|
// append each element
|
||||||
for (const auto& el : *j.m_value.object)
|
for (const auto& el : *j.m_value.object)
|
||||||
|
@ -6772,8 +6822,18 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a JSON value from a given MessagePack vector
|
||||||
|
|
||||||
@param[in] v MessagePack serialization
|
@param[in] v MessagePack serialization
|
||||||
@param[in] idx byte index to start reading from @a v
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from MessagePack were
|
||||||
|
used in the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@sa https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||||
*/
|
*/
|
||||||
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
{
|
{
|
||||||
|
@ -6992,6 +7052,20 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a given CBOR vector
|
||||||
|
|
||||||
|
@param[in] v CBOR serialization
|
||||||
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from CBOR were used in
|
||||||
|
the given vector @a v or if the input is not valid CBOR
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@sa https://tools.ietf.org/html/rfc7049
|
||||||
|
*/
|
||||||
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
|
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
{
|
{
|
||||||
// store and increment index
|
// store and increment index
|
||||||
|
@ -7457,8 +7531,24 @@ class basic_json
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
Serializes a given JSON value @a j to a byte vector using the MessagePack
|
||||||
|
serialization format. MessagePack is a binary serialization format which
|
||||||
|
aims to be more compact than JSON itself, yet more efficient to parse.
|
||||||
|
|
||||||
@param[in] j JSON value to serialize
|
@param[in] j JSON value to serialize
|
||||||
@retuen MessagePack serialization as char vector
|
@return MessagePack serialization as byte vector
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value @a j.
|
||||||
|
|
||||||
|
@liveexample{The example shows the serialization of a JSON value to a byte
|
||||||
|
vector in MessagePack format.,to_msgpack}
|
||||||
|
|
||||||
|
@sa http://msgpack.org
|
||||||
|
@sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
|
||||||
|
deserialization
|
||||||
|
@sa @ref to_cbor(const basic_json& for the related CBOR format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
||||||
{
|
{
|
||||||
|
@ -7467,6 +7557,28 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a byte vector in MessagePack format
|
||||||
|
|
||||||
|
Deserializes a given byte vector @a v to a JSON value using the MessagePack
|
||||||
|
serialization format.
|
||||||
|
|
||||||
|
@param[in] v a byte vector in MessagePack format
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from MessagePack were
|
||||||
|
used in the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@complexity Linear in the size of the byte vector @a v.
|
||||||
|
|
||||||
|
@liveexample{The example shows the deserialization of a byte vector in
|
||||||
|
MessagePack format to a JSON value.,from_msgpack}
|
||||||
|
|
||||||
|
@sa http://msgpack.org
|
||||||
|
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
|
||||||
|
@sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
|
||||||
|
*/
|
||||||
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -7474,8 +7586,25 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
|
||||||
|
Binary Object Representation) serialization format. CBOR is a binary
|
||||||
|
serialization format which aims to be more compact than JSON itself, yet
|
||||||
|
more efficient to parse.
|
||||||
|
|
||||||
@param[in] j JSON value to serialize
|
@param[in] j JSON value to serialize
|
||||||
@retuen CBOR serialization as char vector
|
@return MessagePack serialization as byte vector
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value @a j.
|
||||||
|
|
||||||
|
@liveexample{The example shows the serialization of a JSON value to a byte
|
||||||
|
vector in CBOR format.,to_cbor}
|
||||||
|
|
||||||
|
@sa http://cbor.io
|
||||||
|
@sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
|
||||||
|
deserialization
|
||||||
|
@sa @ref to_msgpack(const basic_json& for the related MessagePack format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
||||||
{
|
{
|
||||||
|
@ -7484,6 +7613,29 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a byte vector in CBOR format
|
||||||
|
|
||||||
|
Deserializes a given byte vector @a v to a JSON value using the CBOR
|
||||||
|
(Concise Binary Object Representation) serialization format.
|
||||||
|
|
||||||
|
@param[in] v a byte vector in CBOR format
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from CBOR were used in
|
||||||
|
the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@complexity Linear in the size of the byte vector @a v.
|
||||||
|
|
||||||
|
@liveexample{The example shows the deserialization of a byte vector in CBOR
|
||||||
|
format to a JSON value.,from_cbor}
|
||||||
|
|
||||||
|
@sa http://cbor.io
|
||||||
|
@sa @ref to_cbor(const basic_json&) for the analogous serialization
|
||||||
|
@sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
|
||||||
|
MessagePack format
|
||||||
|
*/
|
||||||
static basic_json from_cbor(const std::vector<uint8_t>& v)
|
static basic_json from_cbor(const std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
|
@ -6312,6 +6312,16 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
This is a straightforward implementation of the MessagePack specification.
|
||||||
|
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@param[in,out] v byte vector to write the serialization to
|
||||||
|
|
||||||
|
@sa https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||||
|
*/
|
||||||
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
|
@ -6332,34 +6342,72 @@ class basic_json
|
||||||
|
|
||||||
case value_t::number_integer:
|
case value_t::number_integer:
|
||||||
{
|
{
|
||||||
if (j.m_value.number_integer >= -32 and j.m_value.number_integer < 128)
|
if (j.m_value.number_integer >= 0)
|
||||||
{
|
{
|
||||||
// negative fixnum and positive fixnum
|
// MessagePack does not differentiate between positive
|
||||||
add_to_vector(v, 1, j.m_value.number_integer);
|
// signed integers and unsigned integers. Therefore, we used
|
||||||
|
// the code from the value_t::number_unsigned case here.
|
||||||
|
if (j.m_value.number_unsigned < 128)
|
||||||
|
{
|
||||||
|
// positive fixnum
|
||||||
|
add_to_vector(v, 1, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT8_MAX)
|
||||||
|
{
|
||||||
|
// uint 8
|
||||||
|
v.push_back(0xcc);
|
||||||
|
add_to_vector(v, 1, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
// uint 16
|
||||||
|
v.push_back(0xcd);
|
||||||
|
add_to_vector(v, 2, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
// uint 32
|
||||||
|
v.push_back(0xce);
|
||||||
|
add_to_vector(v, 4, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT64_MAX)
|
||||||
|
{
|
||||||
|
// uint 64
|
||||||
|
v.push_back(0xcf);
|
||||||
|
add_to_vector(v, 8, j.m_value.number_unsigned);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
else
|
||||||
{
|
{
|
||||||
// int 8
|
if (j.m_value.number_integer >= -32)
|
||||||
v.push_back(0xd0);
|
{
|
||||||
add_to_vector(v, 1, j.m_value.number_integer);
|
// negative fixnum
|
||||||
}
|
add_to_vector(v, 1, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
||||||
// int 16
|
{
|
||||||
v.push_back(0xd1);
|
// int 8
|
||||||
add_to_vector(v, 2, j.m_value.number_integer);
|
v.push_back(0xd0);
|
||||||
}
|
add_to_vector(v, 1, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
||||||
// int 32
|
{
|
||||||
v.push_back(0xd2);
|
// int 16
|
||||||
add_to_vector(v, 4, j.m_value.number_integer);
|
v.push_back(0xd1);
|
||||||
}
|
add_to_vector(v, 2, j.m_value.number_integer);
|
||||||
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
}
|
||||||
{
|
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
||||||
// int 64
|
{
|
||||||
v.push_back(0xd3);
|
// int 32
|
||||||
add_to_vector(v, 8, j.m_value.number_integer);
|
v.push_back(0xd2);
|
||||||
|
add_to_vector(v, 4, j.m_value.number_integer);
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
||||||
|
{
|
||||||
|
// int 64
|
||||||
|
v.push_back(0xd3);
|
||||||
|
add_to_vector(v, 8, j.m_value.number_integer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6509,6 +6557,16 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a CBOR serialization of a given JSON value
|
||||||
|
|
||||||
|
This is a straightforward implementation of the CBOR specification.
|
||||||
|
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@param[in,out] v byte vector to write the serialization to
|
||||||
|
|
||||||
|
@sa https://tools.ietf.org/html/rfc7049
|
||||||
|
*/
|
||||||
static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
|
static void to_cbor_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
switch (j.type())
|
switch (j.type())
|
||||||
|
@ -6566,7 +6624,7 @@ class basic_json
|
||||||
// The conversions below encode the sign in the first byte,
|
// The conversions below encode the sign in the first byte,
|
||||||
// and the value is converted to a positive number.
|
// and the value is converted to a positive number.
|
||||||
const auto positive_number = -1 - j.m_value.number_integer;
|
const auto positive_number = -1 - j.m_value.number_integer;
|
||||||
if (j.m_value.number_integer <= -1 and j.m_value.number_integer >= -24)
|
if (j.m_value.number_integer >= -24)
|
||||||
{
|
{
|
||||||
v.push_back(static_cast<uint8_t>(0x20 + positive_number));
|
v.push_back(static_cast<uint8_t>(0x20 + positive_number));
|
||||||
}
|
}
|
||||||
|
@ -6648,32 +6706,30 @@ class basic_json
|
||||||
const auto N = j.m_value.string->size();
|
const auto N = j.m_value.string->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
v.push_back(0x60 + N);
|
v.push_back(0x60 + N); // 1 byte for string + size
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0x78);
|
v.push_back(0x78); // one-byte uint8_t for N
|
||||||
// one-byte uint8_t for N
|
|
||||||
add_to_vector(v, 1, N);
|
add_to_vector(v, 1, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x79);
|
v.push_back(0x79); // two-byte uint16_t for N
|
||||||
// two-byte uint16_t for N
|
|
||||||
add_to_vector(v, 2, N);
|
add_to_vector(v, 2, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x7a);
|
v.push_back(0x7a); // four-byte uint32_t for N
|
||||||
// four-byte uint32_t for N
|
|
||||||
add_to_vector(v, 4, N);
|
add_to_vector(v, 4, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x7b);
|
v.push_back(0x7b); // eight-byte uint64_t for N
|
||||||
// eight-byte uint64_t for N
|
|
||||||
add_to_vector(v, 8, N);
|
add_to_vector(v, 8, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append string
|
// append string
|
||||||
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
||||||
|
@ -6686,33 +6742,30 @@ class basic_json
|
||||||
const auto N = j.m_value.array->size();
|
const auto N = j.m_value.array->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
// 1 byte for array + size
|
v.push_back(0x80 + N); // 1 byte for array + size
|
||||||
v.push_back(0x80 + N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0x98);
|
v.push_back(0x98); // one-byte uint8_t for N
|
||||||
// one-byte uint8_t for N
|
|
||||||
add_to_vector(v, 1, N);
|
add_to_vector(v, 1, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x99);
|
v.push_back(0x99); // two-byte uint16_t for N
|
||||||
// two-byte uint16_t for N
|
|
||||||
add_to_vector(v, 2, N);
|
add_to_vector(v, 2, N);
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x9a);
|
v.push_back(0x9a); // four-byte uint32_t for N
|
||||||
// four-byte uint32_t for N
|
|
||||||
add_to_vector(v, 4, N);
|
add_to_vector(v, 4, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0x9b);
|
v.push_back(0x9b); // eight-byte uint64_t for N
|
||||||
// eight-byte uint64_t for N
|
|
||||||
add_to_vector(v, 8, N);
|
add_to_vector(v, 8, N);
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append each element
|
// append each element
|
||||||
for (const auto& el : *j.m_value.array)
|
for (const auto& el : *j.m_value.array)
|
||||||
|
@ -6727,33 +6780,30 @@ class basic_json
|
||||||
const auto N = j.m_value.object->size();
|
const auto N = j.m_value.object->size();
|
||||||
if (N <= 0x17)
|
if (N <= 0x17)
|
||||||
{
|
{
|
||||||
// 1 byte for object + size
|
v.push_back(0xa0 + N); // 1 byte for object + size
|
||||||
v.push_back(0xa0 + N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xff)
|
else if (N <= 0xff)
|
||||||
{
|
{
|
||||||
v.push_back(0xb8);
|
v.push_back(0xb8);
|
||||||
// one-byte uint8_t for N
|
add_to_vector(v, 1, N); // one-byte uint8_t for N
|
||||||
add_to_vector(v, 1, N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xffff)
|
else if (N <= 0xffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xb9);
|
v.push_back(0xb9);
|
||||||
// two-byte uint16_t for N
|
add_to_vector(v, 2, N); // two-byte uint16_t for N
|
||||||
add_to_vector(v, 2, N);
|
|
||||||
}
|
}
|
||||||
else if (N <= 0xffffffff)
|
else if (N <= 0xffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xba);
|
v.push_back(0xba);
|
||||||
// four-byte uint32_t for N
|
add_to_vector(v, 4, N); // four-byte uint32_t for N
|
||||||
add_to_vector(v, 4, N);
|
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_START
|
||||||
else if (N <= 0xffffffffffffffff)
|
else if (N <= 0xffffffffffffffff)
|
||||||
{
|
{
|
||||||
v.push_back(0xbb);
|
v.push_back(0xbb);
|
||||||
// eight-byte uint64_t for N
|
add_to_vector(v, 8, N); // eight-byte uint64_t for N
|
||||||
add_to_vector(v, 8, N);
|
|
||||||
}
|
}
|
||||||
|
// LCOV_EXCL_STOP
|
||||||
|
|
||||||
// append each element
|
// append each element
|
||||||
for (const auto& el : *j.m_value.object)
|
for (const auto& el : *j.m_value.object)
|
||||||
|
@ -6772,8 +6822,18 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a JSON value from a given MessagePack vector
|
||||||
|
|
||||||
@param[in] v MessagePack serialization
|
@param[in] v MessagePack serialization
|
||||||
@param[in] idx byte index to start reading from @a v
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from MessagePack were
|
||||||
|
used in the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@sa https://github.com/msgpack/msgpack/blob/master/spec.md
|
||||||
*/
|
*/
|
||||||
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
{
|
{
|
||||||
|
@ -6992,6 +7052,20 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a given CBOR vector
|
||||||
|
|
||||||
|
@param[in] v CBOR serialization
|
||||||
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from CBOR were used in
|
||||||
|
the given vector @a v or if the input is not valid CBOR
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@sa https://tools.ietf.org/html/rfc7049
|
||||||
|
*/
|
||||||
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
|
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
{
|
{
|
||||||
// store and increment index
|
// store and increment index
|
||||||
|
@ -7457,8 +7531,24 @@ class basic_json
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
Serializes a given JSON value @a j to a byte vector using the MessagePack
|
||||||
|
serialization format. MessagePack is a binary serialization format which
|
||||||
|
aims to be more compact than JSON itself, yet more efficient to parse.
|
||||||
|
|
||||||
@param[in] j JSON value to serialize
|
@param[in] j JSON value to serialize
|
||||||
@retuen MessagePack serialization as char vector
|
@return MessagePack serialization as byte vector
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value @a j.
|
||||||
|
|
||||||
|
@liveexample{The example shows the serialization of a JSON value to a byte
|
||||||
|
vector in MessagePack format.,to_msgpack}
|
||||||
|
|
||||||
|
@sa http://msgpack.org
|
||||||
|
@sa @ref from_msgpack(const std::vector<uint8_t>&) for the analogous
|
||||||
|
deserialization
|
||||||
|
@sa @ref to_cbor(const basic_json& for the related CBOR format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
||||||
{
|
{
|
||||||
|
@ -7467,6 +7557,28 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a byte vector in MessagePack format
|
||||||
|
|
||||||
|
Deserializes a given byte vector @a v to a JSON value using the MessagePack
|
||||||
|
serialization format.
|
||||||
|
|
||||||
|
@param[in] v a byte vector in MessagePack format
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from MessagePack were
|
||||||
|
used in the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@complexity Linear in the size of the byte vector @a v.
|
||||||
|
|
||||||
|
@liveexample{The example shows the deserialization of a byte vector in
|
||||||
|
MessagePack format to a JSON value.,from_msgpack}
|
||||||
|
|
||||||
|
@sa http://msgpack.org
|
||||||
|
@sa @ref to_msgpack(const basic_json&) for the analogous serialization
|
||||||
|
@sa @ref from_cbor(const std::vector<uint8_t>&) for the related CBOR format
|
||||||
|
*/
|
||||||
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
@ -7474,8 +7586,25 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
|
||||||
|
Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
|
||||||
|
Binary Object Representation) serialization format. CBOR is a binary
|
||||||
|
serialization format which aims to be more compact than JSON itself, yet
|
||||||
|
more efficient to parse.
|
||||||
|
|
||||||
@param[in] j JSON value to serialize
|
@param[in] j JSON value to serialize
|
||||||
@retuen CBOR serialization as char vector
|
@return MessagePack serialization as byte vector
|
||||||
|
|
||||||
|
@complexity Linear in the size of the JSON value @a j.
|
||||||
|
|
||||||
|
@liveexample{The example shows the serialization of a JSON value to a byte
|
||||||
|
vector in CBOR format.,to_cbor}
|
||||||
|
|
||||||
|
@sa http://cbor.io
|
||||||
|
@sa @ref from_cbor(const std::vector<uint8_t>&) for the analogous
|
||||||
|
deserialization
|
||||||
|
@sa @ref to_msgpack(const basic_json& for the related MessagePack format
|
||||||
*/
|
*/
|
||||||
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
static std::vector<uint8_t> to_cbor(const basic_json& j)
|
||||||
{
|
{
|
||||||
|
@ -7484,6 +7613,29 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a byte vector in CBOR format
|
||||||
|
|
||||||
|
Deserializes a given byte vector @a v to a JSON value using the CBOR
|
||||||
|
(Concise Binary Object Representation) serialization format.
|
||||||
|
|
||||||
|
@param[in] v a byte vector in CBOR format
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw std::invalid_argument if unsupported features from CBOR were used in
|
||||||
|
the given vector @a v or if the input is not valid MessagePack
|
||||||
|
@throw std::out_of_range if the given vector ends prematurely
|
||||||
|
|
||||||
|
@complexity Linear in the size of the byte vector @a v.
|
||||||
|
|
||||||
|
@liveexample{The example shows the deserialization of a byte vector in CBOR
|
||||||
|
format to a JSON value.,from_cbor}
|
||||||
|
|
||||||
|
@sa http://cbor.io
|
||||||
|
@sa @ref to_cbor(const basic_json&) for the analogous serialization
|
||||||
|
@sa @ref from_msgpack(const std::vector<uint8_t>&) for the related
|
||||||
|
MessagePack format
|
||||||
|
*/
|
||||||
static basic_json from_cbor(const std::vector<uint8_t>& v)
|
static basic_json from_cbor(const std::vector<uint8_t>& v)
|
||||||
{
|
{
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
|
@ -144,6 +144,165 @@ TEST_CASE("MessagePack")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("128..255 (int 8)")
|
||||||
|
{
|
||||||
|
for (size_t i = 128; i <= 255; ++i)
|
||||||
|
{
|
||||||
|
CAPTURE(i);
|
||||||
|
|
||||||
|
// create JSON value with integer number
|
||||||
|
json j = -1;
|
||||||
|
j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
|
||||||
|
|
||||||
|
// check type
|
||||||
|
CHECK(j.is_number_integer());
|
||||||
|
|
||||||
|
// create expected byte vector
|
||||||
|
std::vector<uint8_t> expected;
|
||||||
|
expected.push_back(0xcc);
|
||||||
|
expected.push_back(static_cast<uint8_t>(i));
|
||||||
|
|
||||||
|
// compare result + size
|
||||||
|
const auto result = json::to_msgpack(j);
|
||||||
|
CHECK(result == expected);
|
||||||
|
CHECK(result.size() == 2);
|
||||||
|
|
||||||
|
// check individual bytes
|
||||||
|
CHECK(result[0] == 0xcc);
|
||||||
|
uint8_t restored = static_cast<uint8_t>(result[1]);
|
||||||
|
CHECK(restored == i);
|
||||||
|
|
||||||
|
// roundtrip
|
||||||
|
CHECK(json::from_msgpack(result) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("256..65535 (int 16)")
|
||||||
|
{
|
||||||
|
for (size_t i = 256; i <= 65535; ++i)
|
||||||
|
{
|
||||||
|
CAPTURE(i);
|
||||||
|
|
||||||
|
// create JSON value with integer number
|
||||||
|
json j = -1;
|
||||||
|
j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
|
||||||
|
|
||||||
|
// check type
|
||||||
|
CHECK(j.is_number_integer());
|
||||||
|
|
||||||
|
// create expected byte vector
|
||||||
|
std::vector<uint8_t> expected;
|
||||||
|
expected.push_back(0xcd);
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>(i & 0xff));
|
||||||
|
|
||||||
|
// compare result + size
|
||||||
|
const auto result = json::to_msgpack(j);
|
||||||
|
CHECK(result == expected);
|
||||||
|
CHECK(result.size() == 3);
|
||||||
|
|
||||||
|
// check individual bytes
|
||||||
|
CHECK(result[0] == 0xcd);
|
||||||
|
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||||
|
CHECK(restored == i);
|
||||||
|
|
||||||
|
// roundtrip
|
||||||
|
CHECK(json::from_msgpack(result) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("65536..4294967295 (int 32)")
|
||||||
|
{
|
||||||
|
for (uint32_t i :
|
||||||
|
{
|
||||||
|
65536u, 77777u, 1048576u, 4294967295u
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(i);
|
||||||
|
|
||||||
|
// create JSON value with integer number
|
||||||
|
json j = -1;
|
||||||
|
j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
|
||||||
|
|
||||||
|
// check type
|
||||||
|
CHECK(j.is_number_integer());
|
||||||
|
|
||||||
|
// create expected byte vector
|
||||||
|
std::vector<uint8_t> expected;
|
||||||
|
expected.push_back(0xce);
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>(i & 0xff));
|
||||||
|
|
||||||
|
// compare result + size
|
||||||
|
const auto result = json::to_msgpack(j);
|
||||||
|
CHECK(result == expected);
|
||||||
|
CHECK(result.size() == 5);
|
||||||
|
|
||||||
|
// check individual bytes
|
||||||
|
CHECK(result[0] == 0xce);
|
||||||
|
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||||
|
(static_cast<uint32_t>(result[2]) << 020) +
|
||||||
|
(static_cast<uint32_t>(result[3]) << 010) +
|
||||||
|
static_cast<uint32_t>(result[4]));
|
||||||
|
CHECK(restored == i);
|
||||||
|
|
||||||
|
// roundtrip
|
||||||
|
CHECK(json::from_msgpack(result) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTION("4294967296..9223372036854775807 (int 64)")
|
||||||
|
{
|
||||||
|
for (uint64_t i :
|
||||||
|
{
|
||||||
|
4294967296lu, 9223372036854775807lu
|
||||||
|
})
|
||||||
|
{
|
||||||
|
CAPTURE(i);
|
||||||
|
|
||||||
|
// create JSON value with integer number
|
||||||
|
json j = -1;
|
||||||
|
j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i);
|
||||||
|
|
||||||
|
// check type
|
||||||
|
CHECK(j.is_number_integer());
|
||||||
|
|
||||||
|
// create expected byte vector
|
||||||
|
std::vector<uint8_t> expected;
|
||||||
|
expected.push_back(0xcf);
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff));
|
||||||
|
expected.push_back(static_cast<uint8_t>(i & 0xff));
|
||||||
|
|
||||||
|
// compare result + size
|
||||||
|
const auto result = json::to_msgpack(j);
|
||||||
|
CHECK(result == expected);
|
||||||
|
CHECK(result.size() == 9);
|
||||||
|
|
||||||
|
// check individual bytes
|
||||||
|
CHECK(result[0] == 0xcf);
|
||||||
|
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||||
|
(static_cast<uint64_t>(result[2]) << 060) +
|
||||||
|
(static_cast<uint64_t>(result[3]) << 050) +
|
||||||
|
(static_cast<uint64_t>(result[4]) << 040) +
|
||||||
|
(static_cast<uint64_t>(result[5]) << 030) +
|
||||||
|
(static_cast<uint64_t>(result[6]) << 020) +
|
||||||
|
(static_cast<uint64_t>(result[7]) << 010) +
|
||||||
|
static_cast<uint64_t>(result[8]));
|
||||||
|
CHECK(restored == i);
|
||||||
|
|
||||||
|
// roundtrip
|
||||||
|
CHECK(json::from_msgpack(result) == j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("-128..-33 (int 8)")
|
SECTION("-128..-33 (int 8)")
|
||||||
{
|
{
|
||||||
for (auto i = -128; i <= -33; ++i)
|
for (auto i = -128; i <= -33; ++i)
|
||||||
|
|
Loading…
Reference in a new issue