in MavLinkCom/common_utils/json.hpp [7210:7432]
static basic_json from_msgpack_internal(const std::vector<uint8_t>& v, size_t& idx)
{
// make sure reading 1 byte is safe
check_length(v.size(), 1, idx);
// store and increment index
const size_t current_idx = idx++;
if (v[current_idx] <= 0xbf)
{
if (v[current_idx] <= 0x7f) // positive fixint
{
return v[current_idx];
}
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 // fixstr
{
const size_t len = v[current_idx] & 0x1f;
const size_t offset = current_idx + 1;
idx += len; // skip content bytes
check_length(v.size(), len, offset);
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
}
}
else if (v[current_idx] >= 0xe0) // negative fixint
{
return static_cast<int8_t>(v[current_idx]);
}
else
{
switch (v[current_idx])
{
case 0xc0: // nil
{
return value_t::null;
}
case 0xc2: // false
{
return false;
}
case 0xc3: // true
{
return true;
}
case 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.at(current_idx + 1 + byte);
}
idx += sizeof(float); // skip content bytes
return res;
}
case 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.at(current_idx + 1 + byte);
}
idx += sizeof(double); // skip content bytes
return res;
}
case 0xcc: // uint 8
{
idx += 1; // skip content byte
return get_from_vector<uint8_t>(v, current_idx);
}
case 0xcd: // uint 16
{
idx += 2; // skip 2 content bytes
return get_from_vector<uint16_t>(v, current_idx);
}
case 0xce: // uint 32
{
idx += 4; // skip 4 content bytes
return get_from_vector<uint32_t>(v, current_idx);
}
case 0xcf: // uint 64
{
idx += 8; // skip 8 content bytes
return get_from_vector<uint64_t>(v, current_idx);
}
case 0xd0: // int 8
{
idx += 1; // skip content byte
return get_from_vector<int8_t>(v, current_idx);
}
case 0xd1: // int 16
{
idx += 2; // skip 2 content bytes
return get_from_vector<int16_t>(v, current_idx);
}
case 0xd2: // int 32
{
idx += 4; // skip 4 content bytes
return get_from_vector<int32_t>(v, current_idx);
}
case 0xd3: // int 64
{
idx += 8; // skip 8 content bytes
return get_from_vector<int64_t>(v, current_idx);
}
case 0xd9: // str 8
{
const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
const size_t offset = current_idx + 2;
idx += len + 1; // skip size byte + content bytes
check_length(v.size(), len, offset);
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
}
case 0xda: // str 16
{
const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
const size_t offset = current_idx + 3;
idx += len + 2; // skip 2 size bytes + content bytes
check_length(v.size(), len, offset);
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
}
case 0xdb: // str 32
{
const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
const size_t offset = current_idx + 5;
idx += len + 4; // skip 4 size bytes + content bytes
check_length(v.size(), len, offset);
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
}
case 0xdc: // array 16
{
basic_json result = value_t::array;
const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
idx += 2; // skip 2 size bytes
for (size_t i = 0; i < len; ++i)
{
result.push_back(from_msgpack_internal(v, idx));
}
return result;
}
case 0xdd: // array 32
{
basic_json result = value_t::array;
const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
idx += 4; // skip 4 size bytes
for (size_t i = 0; i < len; ++i)
{
result.push_back(from_msgpack_internal(v, idx));
}
return result;
}
case 0xde: // map 16
{
basic_json result = value_t::object;
const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
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;
}
case 0xdf: // map 32
{
basic_json result = value_t::object;
const auto len = static_cast<size_t>(get_from_vector<uint32_t>(v, current_idx));
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;
}
default:
{
JSON_THROW(std::invalid_argument("error parsing a msgpack @ " + std::to_string(current_idx) + ": " + std::to_string(static_cast<int>(v[current_idx]))));
}
}
}
}