📝 clean up and added documentation for #358

This commit is contained in:
Niels Lohmann 2016-12-11 13:36:08 +01:00
parent fdce38fa79
commit dc6fc3e079
15 changed files with 665 additions and 114 deletions

View 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;
}

View file

@ -0,0 +1 @@
<a target="_blank" href="http://melpon.org/wandbox/permlink/TDPaxmQ7PsvfWxrs"><b>online</b></a>

View file

@ -0,0 +1,4 @@
{
"compact": true,
"schema": 0
}

View 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;
}

View file

@ -0,0 +1 @@
<a target="_blank" href="http://melpon.org/wandbox/permlink/7vRGmLdVcYM7POhE"><b>online</b></a>

View file

@ -0,0 +1,4 @@
{
"compact": true,
"schema": 0
}

19
doc/examples/to_cbor.cpp Normal file
View 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;
}

View file

@ -0,0 +1 @@
<a target="_blank" href="http://melpon.org/wandbox/permlink/UaDbrgZ8OPWaShY8"><b>online</b></a>

View file

@ -0,0 +1 @@
0xa2 0x67 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xf5 0x66 0x73 0x63 0x68 0x65 0x6d 0x61 0x00

View 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;
}

View file

@ -0,0 +1 @@
<a target="_blank" href="http://melpon.org/wandbox/permlink/jvaU8GEfAusb5dKf"><b>online</b></a>

View file

@ -0,0 +1 @@
0x82 0xa7 0x63 0x6f 0x6d 0x70 0x61 0x63 0x74 0xc3 0xa6 0x73 0x63 0x68 0x65 0x6d 0x61 0x00

View file

@ -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,9 +6342,46 @@ 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
// 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 >= -32)
{
// negative fixnum
add_to_vector(v, 1, j.m_value.number_integer); add_to_vector(v, 1, j.m_value.number_integer);
} }
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX) else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
@ -6361,6 +6408,7 @@ class basic_json
v.push_back(0xd3); v.push_back(0xd3);
add_to_vector(v, 8, j.m_value.number_integer); 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;

View file

@ -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,9 +6342,46 @@ 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
// 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 >= -32)
{
// negative fixnum
add_to_vector(v, 1, j.m_value.number_integer); add_to_vector(v, 1, j.m_value.number_integer);
} }
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX) else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
@ -6361,6 +6408,7 @@ class basic_json
v.push_back(0xd3); v.push_back(0xd3);
add_to_vector(v, 8, j.m_value.number_integer); 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;

View file

@ -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)