starting to integrate MessagePack (#358)
This commit is contained in:
parent
9ca00e4880
commit
543745a10e
146 changed files with 1874 additions and 0 deletions
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>menu<EFBFBD>popup<EFBFBD>menuitem<EFBFBD>吶nclick哽reateNewDoc()史alueΛew<65>onclick呢penDoc()史alue力pen<65>onclick杭loseDoc()史alue丘lose█d口ile史alue了ile
|
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 @@
|
||||||
|
‘À
|
1
test/data/json_roundtrip/roundtrip02.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip02.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
妥
|
1
test/data/json_roundtrip/roundtrip03.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip03.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
‘В
|
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 @@
|
||||||
|
‘£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>£foo£bar
|
1
test/data/json_roundtrip/roundtrip10.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip10.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
‚¡aÀ£foo£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>
|
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>
|
1
test/data/json_roundtrip/roundtrip18.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip18.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
‘Ο"τ}ι<>
|
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>
|
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>?鸚<>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 @@
|
||||||
|
懰矿纼n棈
|
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>
|
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 @@
|
||||||
|
騨9ケ 脉<>
|
1
test/data/json_roundtrip/roundtrip31.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip31.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
‘ЛF/)До±Uе
|
1
test/data/json_roundtrip/roundtrip32.json.msgpack
Normal file
1
test/data/json_roundtrip/roundtrip32.json.msgpack
Normal file
|
@ -0,0 +1 @@
|
||||||
|
‘ЛF/)До±Uе
|
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 @@
|
||||||
|
‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘¬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>·JSON Test Pattern pass3‚¬In this test°It is an object.³The outermost value»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 @@
|
||||||
|
草
|
|
@ -0,0 +1 @@
|
||||||
|
蔵
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
‘¡a
|
|
@ -0,0 +1 @@
|
||||||
|
‘В
|
|
@ -0,0 +1 @@
|
||||||
|
”À¡1€
|
|
@ -0,0 +1 @@
|
||||||
|
‘À
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD><01><><EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
▒кMщ2И2╛X╬
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>ث<EFBFBD><EFBFBD>¤<EFBFBD>لhها
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD><EFBFBD><EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD><EFBFBD>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
‘ΛD€πΟMΥ’
|
|
@ -0,0 +1 @@
|
||||||
|
騨?й瓱ョ{
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
‘ËP<EFBFBD>¨¿O§
|
|
@ -0,0 +1 @@
|
||||||
|
騨?й瓱ョ{
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
捜
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD><EFBFBD>@^<5E><<07>
|
|
@ -0,0 +1 @@
|
||||||
|
ぅdfg」fgh」asd」sdf
|
|
@ -0,0 +1 @@
|
||||||
|
▲asd」sdf
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>¡a¡c
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>¡a¡b
|
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
‚£maxËEÀ'ç/<12>£minËÅÀ'ç/<12>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>¡a<EFBFBD>
|
Binary file not shown.
|
@ -0,0 +1 @@
|
||||||
|
<EFBFBD>¡a¡b
|
|
@ -0,0 +1 @@
|
||||||
|
即`トェ瘧ォ
|
|
@ -0,0 +1 @@
|
||||||
|
側<EFBFBD><EFBFBD>
|
|
@ -0,0 +1 @@
|
||||||
|
側<EFBFBD>盛
|
|
@ -0,0 +1 @@
|
||||||
|
捉<EFBFBD>仍<EFBFBD>注
|
|
@ -0,0 +1,2 @@
|
||||||
|
捉"\/
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
即\u0000
|
|
@ -0,0 +1 @@
|
||||||
|
贈"
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue