mirror of
https://github.com/nlohmann/json.git
synced 2025-07-29 23:01:16 +03:00
starting to integrate MessagePack (#358)
This commit is contained in:
493
src/json.hpp
493
src/json.hpp
@ -6142,6 +6142,499 @@ class basic_json
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
// MessagePack support //
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
/// @name MessagePack support
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
|
{
|
||||||
|
switch (j.type())
|
||||||
|
{
|
||||||
|
case value_t::null:
|
||||||
|
{
|
||||||
|
// nil
|
||||||
|
v.push_back(0xc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::boolean:
|
||||||
|
{
|
||||||
|
// true and false
|
||||||
|
v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_integer:
|
||||||
|
{
|
||||||
|
if (j.m_value.number_integer >= -32 and j.m_value.number_integer < 128)
|
||||||
|
{
|
||||||
|
// negative fixnum and positive fixnum
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
||||||
|
{
|
||||||
|
// int 8
|
||||||
|
v.push_back(0xd0);
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
||||||
|
{
|
||||||
|
// int 16
|
||||||
|
v.push_back(0xd1);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
||||||
|
{
|
||||||
|
// int 32
|
||||||
|
v.push_back(0xd2);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
||||||
|
{
|
||||||
|
// int 64
|
||||||
|
v.push_back(0xd3);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 070) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 060) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 050) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 040) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_unsigned:
|
||||||
|
{
|
||||||
|
if (j.m_value.number_unsigned < 128)
|
||||||
|
{
|
||||||
|
// positive fixnum
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT8_MAX)
|
||||||
|
{
|
||||||
|
// uint 8
|
||||||
|
v.push_back(0xcc);
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
// uint 16
|
||||||
|
v.push_back(0xcd);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
// uint 32
|
||||||
|
v.push_back(0xce);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT64_MAX)
|
||||||
|
{
|
||||||
|
// uint 64
|
||||||
|
v.push_back(0xcf);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 070) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 060) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 050) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 040) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_float:
|
||||||
|
{
|
||||||
|
// float 64
|
||||||
|
v.push_back(0xcb);
|
||||||
|
const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
|
||||||
|
for (size_t i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
v.push_back(helper[7 - i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::string:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.string->size();
|
||||||
|
if (N <= 31)
|
||||||
|
{
|
||||||
|
// fixstr
|
||||||
|
v.push_back(static_cast<uint8_t>(0xa0 | N));
|
||||||
|
}
|
||||||
|
else if (N <= 255)
|
||||||
|
{
|
||||||
|
// str 8
|
||||||
|
v.push_back(0xd9);
|
||||||
|
v.push_back(static_cast<uint8_t>(N));
|
||||||
|
}
|
||||||
|
else if (N <= 65535)
|
||||||
|
{
|
||||||
|
// str 16
|
||||||
|
v.push_back(0xda);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 4294967295)
|
||||||
|
{
|
||||||
|
// str 32
|
||||||
|
v.push_back(0xdb);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append string
|
||||||
|
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
||||||
|
std::back_inserter(v));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.array->size();
|
||||||
|
if (N <= 15)
|
||||||
|
{
|
||||||
|
// fixarray
|
||||||
|
v.push_back(static_cast<uint8_t>(0x90 | N));
|
||||||
|
}
|
||||||
|
else if (N <= 0xffff)
|
||||||
|
{
|
||||||
|
// array 16
|
||||||
|
v.push_back(0xdc);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 0xffffffff)
|
||||||
|
{
|
||||||
|
// array 32
|
||||||
|
v.push_back(0xdd);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append each element
|
||||||
|
for (const auto& el : *j.m_value.array)
|
||||||
|
{
|
||||||
|
to_msgpack_internal(el, v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.object->size();
|
||||||
|
if (N <= 15)
|
||||||
|
{
|
||||||
|
// fixmap
|
||||||
|
v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
|
||||||
|
}
|
||||||
|
else if (N <= 65535)
|
||||||
|
{
|
||||||
|
// map 16
|
||||||
|
v.push_back(0xde);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 4294967295)
|
||||||
|
{
|
||||||
|
// map 32
|
||||||
|
v.push_back(0xdf);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append each element
|
||||||
|
for (const auto& el : *j.m_value.object)
|
||||||
|
{
|
||||||
|
to_msgpack_internal(el.first, v);
|
||||||
|
to_msgpack_internal(el.second, v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] v MessagePack serialization
|
||||||
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
*/
|
||||||
|
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
|
{
|
||||||
|
// store and increment index
|
||||||
|
const size_t current_idx = idx++;
|
||||||
|
|
||||||
|
if (v[current_idx] <= 0x7f) // positive fixint
|
||||||
|
{
|
||||||
|
return v[current_idx];
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0x8f) // fixmap
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = v[current_idx] & 0x0f;
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0x9f) // fixarray
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = v[current_idx] & 0x0f;
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0xbf) // fixstr
|
||||||
|
{
|
||||||
|
const size_t len = v[current_idx] & 0x1f;
|
||||||
|
const size_t offset = current_idx + 1;
|
||||||
|
idx += len; // skip content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc0) // nil
|
||||||
|
{
|
||||||
|
return value_t::null;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc1) // never used
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("value 0x31 must not be used@ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc2) // false
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc3) // true
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xc4 and v[current_idx] <= 0xc9) // bin/ext
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("bin/ext are not supported @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xca) // float 32
|
||||||
|
{
|
||||||
|
// copy bytes in reverse order into the double variable
|
||||||
|
float res;
|
||||||
|
for (size_t byte = 0; byte < sizeof(float); ++byte)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
|
||||||
|
}
|
||||||
|
idx += sizeof(float); // skip content bytes
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcb) // float 64
|
||||||
|
{
|
||||||
|
// copy bytes in reverse order into the double variable
|
||||||
|
double res;
|
||||||
|
for (size_t byte = 0; byte < sizeof(double); ++byte)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
|
||||||
|
}
|
||||||
|
idx += sizeof(double); // skip content bytes
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcc) // uint 8
|
||||||
|
{
|
||||||
|
idx += 1; // skip content byte
|
||||||
|
return v[current_idx + 1];
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcd) // uint 16
|
||||||
|
{
|
||||||
|
idx += 2; // skip 2 content bytes
|
||||||
|
return static_cast<uint16_t>((static_cast<uint16_t>(v[current_idx + 1]) << 010) +
|
||||||
|
static_cast<uint16_t>(v[current_idx + 2]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xce) // uint 32
|
||||||
|
{
|
||||||
|
idx += 4; // skip 4 content bytes
|
||||||
|
return static_cast<uint32_t>((static_cast<uint32_t>(v[current_idx + 1]) << 030) +
|
||||||
|
(static_cast<uint32_t>(v[current_idx + 2]) << 020) +
|
||||||
|
(static_cast<uint32_t>(v[current_idx + 3]) << 010) +
|
||||||
|
static_cast<uint32_t>(v[current_idx + 4]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcf) // uint 64
|
||||||
|
{
|
||||||
|
idx += 8; // skip 8 content bytes
|
||||||
|
return static_cast<uint64_t>((static_cast<uint64_t>(v[current_idx + 1]) << 070) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 2]) << 060) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 3]) << 050) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 4]) << 040) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 5]) << 030) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 6]) << 020) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 7]) << 010) +
|
||||||
|
static_cast<uint64_t>(v[current_idx + 8]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd0) // int 8
|
||||||
|
{
|
||||||
|
idx += 1; // skip content byte
|
||||||
|
return static_cast<int8_t>(v[current_idx + 1]);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd1) // int 16
|
||||||
|
{
|
||||||
|
idx += 2; // skip 2 content bytes
|
||||||
|
return static_cast<int16_t>((static_cast<int16_t>(v[current_idx + 1]) << 010) +
|
||||||
|
static_cast<int16_t>(v[current_idx + 2]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd2) // int 32
|
||||||
|
{
|
||||||
|
idx += 4; // skip 4 content bytes
|
||||||
|
return static_cast<int32_t>((static_cast<int32_t>(v[current_idx + 1]) << 030) +
|
||||||
|
(static_cast<int32_t>(v[current_idx + 2]) << 020) +
|
||||||
|
(static_cast<int32_t>(v[current_idx + 3]) << 010) +
|
||||||
|
static_cast<int32_t>(v[current_idx + 4]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd3) // int 64
|
||||||
|
{
|
||||||
|
idx += 8; // skip 8 content bytes
|
||||||
|
return static_cast<int64_t>((static_cast<int64_t>(v[current_idx + 1]) << 070) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 2]) << 060) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 3]) << 050) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 4]) << 040) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 5]) << 030) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 6]) << 020) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 7]) << 010) +
|
||||||
|
static_cast<int64_t>(v[current_idx + 8]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xd4 and v[current_idx] <= 0xd8) // fixext
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("bin/ext are not supported @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd9) // str 8
|
||||||
|
{
|
||||||
|
const size_t len = v[current_idx + 1];
|
||||||
|
const size_t offset = current_idx + 2;
|
||||||
|
idx += len + 1; // skip size byte + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xda) // str 16
|
||||||
|
{
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) + v[current_idx + 2]);
|
||||||
|
const size_t offset = current_idx + 3;
|
||||||
|
idx += len + 2; // skip 2 size bytes + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdb) // str 32
|
||||||
|
{
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
const size_t offset = current_idx + 5;
|
||||||
|
idx += len + 4; // skip 4 size bytes + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdc) // array 16
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) +
|
||||||
|
v[current_idx + 2]);
|
||||||
|
idx += 2; // skip 2 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdd) // array 32
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
idx += 4; // skip 4 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xde) // map 16
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) +
|
||||||
|
v[current_idx + 2]);
|
||||||
|
idx += 2; // skip 2 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdf) // map 32
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
idx += 4; // skip 4 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xe0) // negative fixint
|
||||||
|
{
|
||||||
|
return static_cast<int8_t>(v[current_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@retuen MessagePack serialization as char vector
|
||||||
|
*/
|
||||||
|
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
to_msgpack_internal(j, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
return from_msgpack_internal(v, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
|
@ -6142,6 +6142,499 @@ class basic_json
|
|||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/////////////////////////
|
||||||
|
// MessagePack support //
|
||||||
|
/////////////////////////
|
||||||
|
|
||||||
|
/// @name MessagePack support
|
||||||
|
/// @{
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void to_msgpack_internal(const basic_json& j, std::vector<uint8_t>& v)
|
||||||
|
{
|
||||||
|
switch (j.type())
|
||||||
|
{
|
||||||
|
case value_t::null:
|
||||||
|
{
|
||||||
|
// nil
|
||||||
|
v.push_back(0xc0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::boolean:
|
||||||
|
{
|
||||||
|
// true and false
|
||||||
|
v.push_back(j.m_value.boolean ? 0xc3 : 0xc2);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_integer:
|
||||||
|
{
|
||||||
|
if (j.m_value.number_integer >= -32 and j.m_value.number_integer < 128)
|
||||||
|
{
|
||||||
|
// negative fixnum and positive fixnum
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT8_MIN and j.m_value.number_integer <= INT8_MAX)
|
||||||
|
{
|
||||||
|
// int 8
|
||||||
|
v.push_back(0xd0);
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT16_MIN and j.m_value.number_integer <= INT16_MAX)
|
||||||
|
{
|
||||||
|
// int 16
|
||||||
|
v.push_back(0xd1);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT32_MIN and j.m_value.number_integer <= INT32_MAX)
|
||||||
|
{
|
||||||
|
// int 32
|
||||||
|
v.push_back(0xd2);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_integer >= INT64_MIN and j.m_value.number_integer <= INT64_MAX)
|
||||||
|
{
|
||||||
|
// int 64
|
||||||
|
v.push_back(0xd3);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 070) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 060) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 050) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 040) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_integer >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_integer & 0xff));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_unsigned:
|
||||||
|
{
|
||||||
|
if (j.m_value.number_unsigned < 128)
|
||||||
|
{
|
||||||
|
// positive fixnum
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT8_MAX)
|
||||||
|
{
|
||||||
|
// uint 8
|
||||||
|
v.push_back(0xcc);
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT16_MAX)
|
||||||
|
{
|
||||||
|
// uint 16
|
||||||
|
v.push_back(0xcd);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT32_MAX)
|
||||||
|
{
|
||||||
|
// uint 32
|
||||||
|
v.push_back(0xce);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
else if (j.m_value.number_unsigned <= UINT64_MAX)
|
||||||
|
{
|
||||||
|
// uint 64
|
||||||
|
v.push_back(0xcf);
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 070) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 060) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 050) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 040) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((j.m_value.number_unsigned >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(j.m_value.number_unsigned & 0xff));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::number_float:
|
||||||
|
{
|
||||||
|
// float 64
|
||||||
|
v.push_back(0xcb);
|
||||||
|
const uint8_t* helper = reinterpret_cast<const uint8_t*>(&(j.m_value.number_float));
|
||||||
|
for (size_t i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
v.push_back(helper[7 - i]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::string:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.string->size();
|
||||||
|
if (N <= 31)
|
||||||
|
{
|
||||||
|
// fixstr
|
||||||
|
v.push_back(static_cast<uint8_t>(0xa0 | N));
|
||||||
|
}
|
||||||
|
else if (N <= 255)
|
||||||
|
{
|
||||||
|
// str 8
|
||||||
|
v.push_back(0xd9);
|
||||||
|
v.push_back(static_cast<uint8_t>(N));
|
||||||
|
}
|
||||||
|
else if (N <= 65535)
|
||||||
|
{
|
||||||
|
// str 16
|
||||||
|
v.push_back(0xda);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 4294967295)
|
||||||
|
{
|
||||||
|
// str 32
|
||||||
|
v.push_back(0xdb);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append string
|
||||||
|
std::copy(j.m_value.string->begin(), j.m_value.string->end(),
|
||||||
|
std::back_inserter(v));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.array->size();
|
||||||
|
if (N <= 15)
|
||||||
|
{
|
||||||
|
// fixarray
|
||||||
|
v.push_back(static_cast<uint8_t>(0x90 | N));
|
||||||
|
}
|
||||||
|
else if (N <= 0xffff)
|
||||||
|
{
|
||||||
|
// array 16
|
||||||
|
v.push_back(0xdc);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 0xffffffff)
|
||||||
|
{
|
||||||
|
// array 32
|
||||||
|
v.push_back(0xdd);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append each element
|
||||||
|
for (const auto& el : *j.m_value.array)
|
||||||
|
{
|
||||||
|
to_msgpack_internal(el, v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
const auto N = j.m_value.object->size();
|
||||||
|
if (N <= 15)
|
||||||
|
{
|
||||||
|
// fixmap
|
||||||
|
v.push_back(static_cast<uint8_t>(0x80 | (N & 0xf)));
|
||||||
|
}
|
||||||
|
else if (N <= 65535)
|
||||||
|
{
|
||||||
|
// map 16
|
||||||
|
v.push_back(0xde);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
else if (N <= 4294967295)
|
||||||
|
{
|
||||||
|
// map 32
|
||||||
|
v.push_back(0xdf);
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 030) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 020) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>((N >> 010) & 0xff));
|
||||||
|
v.push_back(static_cast<uint8_t>(N & 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
// append each element
|
||||||
|
for (const auto& el : *j.m_value.object)
|
||||||
|
{
|
||||||
|
to_msgpack_internal(el.first, v);
|
||||||
|
to_msgpack_internal(el.second, v);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] v MessagePack serialization
|
||||||
|
@param[in] idx byte index to start reading from @a v
|
||||||
|
*/
|
||||||
|
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
|
||||||
|
{
|
||||||
|
// store and increment index
|
||||||
|
const size_t current_idx = idx++;
|
||||||
|
|
||||||
|
if (v[current_idx] <= 0x7f) // positive fixint
|
||||||
|
{
|
||||||
|
return v[current_idx];
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0x8f) // fixmap
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = v[current_idx] & 0x0f;
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0x9f) // fixarray
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = v[current_idx] & 0x0f;
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] <= 0xbf) // fixstr
|
||||||
|
{
|
||||||
|
const size_t len = v[current_idx] & 0x1f;
|
||||||
|
const size_t offset = current_idx + 1;
|
||||||
|
idx += len; // skip content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc0) // nil
|
||||||
|
{
|
||||||
|
return value_t::null;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc1) // never used
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("value 0x31 must not be used@ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc2) // false
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xc3) // true
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xc4 and v[current_idx] <= 0xc9) // bin/ext
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("bin/ext are not supported @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xca) // float 32
|
||||||
|
{
|
||||||
|
// copy bytes in reverse order into the double variable
|
||||||
|
float res;
|
||||||
|
for (size_t byte = 0; byte < sizeof(float); ++byte)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint8_t*>(&res)[sizeof(float) - byte - 1] = v[current_idx + 1 + byte];
|
||||||
|
}
|
||||||
|
idx += sizeof(float); // skip content bytes
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcb) // float 64
|
||||||
|
{
|
||||||
|
// copy bytes in reverse order into the double variable
|
||||||
|
double res;
|
||||||
|
for (size_t byte = 0; byte < sizeof(double); ++byte)
|
||||||
|
{
|
||||||
|
reinterpret_cast<uint8_t*>(&res)[sizeof(double) - byte - 1] = v[current_idx + 1 + byte];
|
||||||
|
}
|
||||||
|
idx += sizeof(double); // skip content bytes
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcc) // uint 8
|
||||||
|
{
|
||||||
|
idx += 1; // skip content byte
|
||||||
|
return v[current_idx + 1];
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcd) // uint 16
|
||||||
|
{
|
||||||
|
idx += 2; // skip 2 content bytes
|
||||||
|
return static_cast<uint16_t>((static_cast<uint16_t>(v[current_idx + 1]) << 010) +
|
||||||
|
static_cast<uint16_t>(v[current_idx + 2]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xce) // uint 32
|
||||||
|
{
|
||||||
|
idx += 4; // skip 4 content bytes
|
||||||
|
return static_cast<uint32_t>((static_cast<uint32_t>(v[current_idx + 1]) << 030) +
|
||||||
|
(static_cast<uint32_t>(v[current_idx + 2]) << 020) +
|
||||||
|
(static_cast<uint32_t>(v[current_idx + 3]) << 010) +
|
||||||
|
static_cast<uint32_t>(v[current_idx + 4]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xcf) // uint 64
|
||||||
|
{
|
||||||
|
idx += 8; // skip 8 content bytes
|
||||||
|
return static_cast<uint64_t>((static_cast<uint64_t>(v[current_idx + 1]) << 070) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 2]) << 060) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 3]) << 050) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 4]) << 040) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 5]) << 030) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 6]) << 020) +
|
||||||
|
(static_cast<uint64_t>(v[current_idx + 7]) << 010) +
|
||||||
|
static_cast<uint64_t>(v[current_idx + 8]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd0) // int 8
|
||||||
|
{
|
||||||
|
idx += 1; // skip content byte
|
||||||
|
return static_cast<int8_t>(v[current_idx + 1]);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd1) // int 16
|
||||||
|
{
|
||||||
|
idx += 2; // skip 2 content bytes
|
||||||
|
return static_cast<int16_t>((static_cast<int16_t>(v[current_idx + 1]) << 010) +
|
||||||
|
static_cast<int16_t>(v[current_idx + 2]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd2) // int 32
|
||||||
|
{
|
||||||
|
idx += 4; // skip 4 content bytes
|
||||||
|
return static_cast<int32_t>((static_cast<int32_t>(v[current_idx + 1]) << 030) +
|
||||||
|
(static_cast<int32_t>(v[current_idx + 2]) << 020) +
|
||||||
|
(static_cast<int32_t>(v[current_idx + 3]) << 010) +
|
||||||
|
static_cast<int32_t>(v[current_idx + 4]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd3) // int 64
|
||||||
|
{
|
||||||
|
idx += 8; // skip 8 content bytes
|
||||||
|
return static_cast<int64_t>((static_cast<int64_t>(v[current_idx + 1]) << 070) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 2]) << 060) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 3]) << 050) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 4]) << 040) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 5]) << 030) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 6]) << 020) +
|
||||||
|
(static_cast<int64_t>(v[current_idx + 7]) << 010) +
|
||||||
|
static_cast<int64_t>(v[current_idx + 8]));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xd4 and v[current_idx] <= 0xd8) // fixext
|
||||||
|
{
|
||||||
|
throw std::invalid_argument("bin/ext are not supported @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xd9) // str 8
|
||||||
|
{
|
||||||
|
const size_t len = v[current_idx + 1];
|
||||||
|
const size_t offset = current_idx + 2;
|
||||||
|
idx += len + 1; // skip size byte + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xda) // str 16
|
||||||
|
{
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) + v[current_idx + 2]);
|
||||||
|
const size_t offset = current_idx + 3;
|
||||||
|
idx += len + 2; // skip 2 size bytes + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdb) // str 32
|
||||||
|
{
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
const size_t offset = current_idx + 5;
|
||||||
|
idx += len + 4; // skip 4 size bytes + content bytes
|
||||||
|
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdc) // array 16
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) +
|
||||||
|
v[current_idx + 2]);
|
||||||
|
idx += 2; // skip 2 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdd) // array 32
|
||||||
|
{
|
||||||
|
basic_json result = value_t::array;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
idx += 4; // skip 4 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
result.push_back(from_msgpack_internal(v, idx));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xde) // map 16
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 010) +
|
||||||
|
v[current_idx + 2]);
|
||||||
|
idx += 2; // skip 2 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] == 0xdf) // map 32
|
||||||
|
{
|
||||||
|
basic_json result = value_t::object;
|
||||||
|
const size_t len = static_cast<size_t>((v[current_idx + 1] << 030) +
|
||||||
|
(v[current_idx + 2] << 020) +
|
||||||
|
(v[current_idx + 3] << 010) +
|
||||||
|
v[current_idx + 4]);
|
||||||
|
idx += 4; // skip 4 size bytes
|
||||||
|
for (size_t i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
std::string key = from_msgpack_internal(v, idx);
|
||||||
|
result[key] = from_msgpack_internal(v, idx);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
else if (v[current_idx] >= 0xe0) // negative fixint
|
||||||
|
{
|
||||||
|
return static_cast<int8_t>(v[current_idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx));
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
/*!
|
||||||
|
@param[in] j JSON value to serialize
|
||||||
|
@retuen MessagePack serialization as char vector
|
||||||
|
*/
|
||||||
|
static std::vector<uint8_t> to_msgpack(const basic_json& j)
|
||||||
|
{
|
||||||
|
std::vector<uint8_t> result;
|
||||||
|
to_msgpack_internal(j, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static basic_json from_msgpack(const std::vector<uint8_t>& v)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
return from_msgpack_internal(v, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
@ -7802,6 +8295,7 @@ class basic_json
|
|||||||
re2c:define:YYMARKER = m_marker;
|
re2c:define:YYMARKER = m_marker;
|
||||||
re2c:define:YYFILL = "fill_line_buffer(@@); // LCOV_EXCL_LINE";
|
re2c:define:YYFILL = "fill_line_buffer(@@); // LCOV_EXCL_LINE";
|
||||||
re2c:define:YYFILL:naked = 1;
|
re2c:define:YYFILL:naked = 1;
|
||||||
|
re2c:yyfill:enable = 1;
|
||||||
re2c:indent:string = " ";
|
re2c:indent:string = " ";
|
||||||
re2c:indent:top = 1;
|
re2c:indent:top = 1;
|
||||||
re2c:labelprefix = "basic_json_parser_";
|
re2c:labelprefix = "basic_json_parser_";
|
||||||
|
@ -26,6 +26,7 @@ add_executable(${JSON_UNITTEST_TARGET_NAME}
|
|||||||
"src/unit-json_patch.cpp"
|
"src/unit-json_patch.cpp"
|
||||||
"src/unit-json_pointer.cpp"
|
"src/unit-json_pointer.cpp"
|
||||||
"src/unit-modifiers.cpp"
|
"src/unit-modifiers.cpp"
|
||||||
|
"src/unit-msgpack.cpp"
|
||||||
"src/unit-pointer_access.cpp"
|
"src/unit-pointer_access.cpp"
|
||||||
"src/unit-readme.cpp"
|
"src/unit-readme.cpp"
|
||||||
"src/unit-reference_access.cpp"
|
"src/unit-reference_access.cpp"
|
||||||
|
@ -30,6 +30,7 @@ SOURCES = src/unit.cpp \
|
|||||||
src/unit-json_patch.cpp \
|
src/unit-json_patch.cpp \
|
||||||
src/unit-json_pointer.cpp \
|
src/unit-json_pointer.cpp \
|
||||||
src/unit-modifiers.cpp \
|
src/unit-modifiers.cpp \
|
||||||
|
src/unit-msgpack.cpp \
|
||||||
src/unit-pointer_access.cpp \
|
src/unit-pointer_access.cpp \
|
||||||
src/unit-readme.cpp \
|
src/unit-readme.cpp \
|
||||||
src/unit-reference_access.cpp \
|
src/unit-reference_access.cpp \
|
||||||
|
BIN
test/data/json.org/1.json.msgpack
Normal file
BIN
test/data/json.org/1.json.msgpack
Normal file
Binary file not shown.
1
test/data/json.org/2.json.msgpack
Normal file
1
test/data/json.org/2.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>menu<EFBFBD><EFBFBD>popup<EFBFBD><EFBFBD>menuitem<EFBFBD><EFBFBD><EFBFBD>onclick<EFBFBD>CreateNewDoc()<29>value<75>New<65><77>onclick<63>OpenDoc()<29>value<75>Open<65><6E>onclick<63>CloseDoc()<29>value<75>Close<73>id<69>file<6C>value<75>File
|
BIN
test/data/json.org/3.json.msgpack
Normal file
BIN
test/data/json.org/3.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json.org/4.json.msgpack
Normal file
BIN
test/data/json.org/4.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json.org/5.json.msgpack
Normal file
BIN
test/data/json.org/5.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json_nlohmann_tests/all_unicode.json.msgpack
Normal file
BIN
test/data/json_nlohmann_tests/all_unicode.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip01.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip01.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
1
test/data/json_roundtrip/roundtrip02.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip02.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
1
test/data/json_roundtrip/roundtrip03.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip03.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
BIN
test/data/json_roundtrip/roundtrip04.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip04.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip05.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip05.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>foo
|
1
test/data/json_roundtrip/roundtrip06.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip06.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
1
test/data/json_roundtrip/roundtrip07.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip07.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
BIN
test/data/json_roundtrip/roundtrip08.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip08.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip09.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip09.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>foo<EFBFBD>bar
|
1
test/data/json_roundtrip/roundtrip10.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip10.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a<EFBFBD><EFBFBD>foo<EFBFBD>bar
|
1
test/data/json_roundtrip/roundtrip11.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip11.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
BIN
test/data/json_roundtrip/roundtrip12.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip12.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip13.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip13.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><0B>~<7E>
|
BIN
test/data/json_roundtrip/roundtrip14.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip14.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip15.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip15.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
1
test/data/json_roundtrip/roundtrip16.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip16.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
1
test/data/json_roundtrip/roundtrip17.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip17.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
1
test/data/json_roundtrip/roundtrip18.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip18.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>"<10>}<7D><>
|
1
test/data/json_roundtrip/roundtrip19.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip19.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
BIN
test/data/json_roundtrip/roundtrip20.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip20.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json_roundtrip/roundtrip21.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip21.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip22.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip22.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>?<3F><><EFBFBD>n<><6E>
|
1
test/data/json_roundtrip/roundtrip23.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip23.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>˿<EFBFBD><EFBFBD><EFBFBD>n<><6E>
|
BIN
test/data/json_roundtrip/roundtrip24.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip24.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json_roundtrip/roundtrip25.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip25.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json_roundtrip/roundtrip26.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip26.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip27.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip27.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
BIN
test/data/json_roundtrip/roundtrip28.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip28.json.msgpack
Normal file
Binary file not shown.
BIN
test/data/json_roundtrip/roundtrip29.json.msgpack
Normal file
BIN
test/data/json_roundtrip/roundtrip29.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_roundtrip/roundtrip30.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip30.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>9<EFBFBD> <09><><EFBFBD><EFBFBD>
|
1
test/data/json_roundtrip/roundtrip31.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip31.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>F/)<29><><EFBFBD>U<EFBFBD>
|
1
test/data/json_roundtrip/roundtrip32.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip32.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>F/)<29><><EFBFBD>U<EFBFBD>
|
BIN
test/data/json_tests/pass1.json.msgpack
Normal file
BIN
test/data/json_tests/pass1.json.msgpack
Normal file
Binary file not shown.
1
test/data/json_tests/pass2.json.msgpack
Normal file
1
test/data/json_tests/pass2.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Not too deep
|
1
test/data/json_tests/pass3.json.msgpack
Normal file
1
test/data/json_tests/pass3.json.msgpack
Normal file
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>JSON Test Pattern pass3<73><33>In this test<73>It is an object.<2E>The outermost value<75>must be an object or array.
|
BIN
test/data/json_testsuite/sample.json.msgpack
Normal file
BIN
test/data/json_testsuite/sample.json.msgpack
Normal file
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD><01>1<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><01><><EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>M<EFBFBD>2<EFBFBD>2<EFBFBD>X<EFBFBD>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>˯<EFBFBD><EFBFBD><EFBFBD><EFBFBD>h<EFBFBD><EFBFBD>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>Ѕ
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>
|
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>D<EFBFBD><EFBFBD><EFBFBD>MՒ
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>?<3F>z<EFBFBD>G<EFBFBD>{
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>P<EFBFBD><EFBFBD><EFBFBD>O§
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>?<3F>z<EFBFBD>G<EFBFBD>{
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>{
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>@^<5E><<07>
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>dfg<EFBFBD>fgh<EFBFBD>asd<EFBFBD>sdf
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>asd<EFBFBD>sdf
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a<EFBFBD>c
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a<EFBFBD>b
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD>
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>max<EFBFBD>E<EFBFBD>'<27>/<12><>min<69><6E><EFBFBD>'<27>/<12>
|
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a<EFBFBD>
|
Binary file not shown.
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>a<EFBFBD>b
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>`Īካ
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>𝄞
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>𐐷
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>😹💍
|
@ -0,0 +1,2 @@
|
|||||||
|
<EFBFBD><EFBFBD>"\/
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>\u0000
|
@ -0,0 +1 @@
|
|||||||
|
<EFBFBD><EFBFBD>"
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user