🔨 cleanup
This commit is contained in:
parent
ea667db446
commit
782570d46f
1 changed files with 89 additions and 594 deletions
683
src/json.hpp
683
src/json.hpp
|
@ -8397,505 +8397,6 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief create a JSON value from a given CBOR vector
|
|
||||||
|
|
||||||
@param[in] v CBOR serialization
|
|
||||||
@param[in] idx byte index to start reading from @a v
|
|
||||||
|
|
||||||
@return deserialized JSON value
|
|
||||||
|
|
||||||
@throw parse_error.110 if the given vector ends prematurely
|
|
||||||
@throw parse_error.112 if unsupported features from CBOR were
|
|
||||||
used in the given vector @a v or if the input is not valid CBOR
|
|
||||||
@throw parse_error.113 if a string was expected as map key, but not found
|
|
||||||
|
|
||||||
@sa https://tools.ietf.org/html/rfc7049
|
|
||||||
*/
|
|
||||||
static basic_json from_cbor_internal(const std::vector<uint8_t>& v, size_t& idx)
|
|
||||||
{
|
|
||||||
// store and increment index
|
|
||||||
const size_t current_idx = idx++;
|
|
||||||
|
|
||||||
// make sure reading 1 byte is safe
|
|
||||||
check_length(v.size(), 1, current_idx);
|
|
||||||
|
|
||||||
switch (v[current_idx])
|
|
||||||
{
|
|
||||||
// Integer 0x00..0x17 (0..23)
|
|
||||||
case 0x00:
|
|
||||||
case 0x01:
|
|
||||||
case 0x02:
|
|
||||||
case 0x03:
|
|
||||||
case 0x04:
|
|
||||||
case 0x05:
|
|
||||||
case 0x06:
|
|
||||||
case 0x07:
|
|
||||||
case 0x08:
|
|
||||||
case 0x09:
|
|
||||||
case 0x0a:
|
|
||||||
case 0x0b:
|
|
||||||
case 0x0c:
|
|
||||||
case 0x0d:
|
|
||||||
case 0x0e:
|
|
||||||
case 0x0f:
|
|
||||||
case 0x10:
|
|
||||||
case 0x11:
|
|
||||||
case 0x12:
|
|
||||||
case 0x13:
|
|
||||||
case 0x14:
|
|
||||||
case 0x15:
|
|
||||||
case 0x16:
|
|
||||||
case 0x17:
|
|
||||||
{
|
|
||||||
return v[current_idx];
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x18: // Unsigned integer (one-byte uint8_t follows)
|
|
||||||
{
|
|
||||||
idx += 1; // skip content byte
|
|
||||||
return get_from_vector<uint8_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x19: // Unsigned integer (two-byte uint16_t follows)
|
|
||||||
{
|
|
||||||
idx += 2; // skip 2 content bytes
|
|
||||||
return get_from_vector<uint16_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x1a: // Unsigned integer (four-byte uint32_t follows)
|
|
||||||
{
|
|
||||||
idx += 4; // skip 4 content bytes
|
|
||||||
return get_from_vector<uint32_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x1b: // Unsigned integer (eight-byte uint64_t follows)
|
|
||||||
{
|
|
||||||
idx += 8; // skip 8 content bytes
|
|
||||||
return get_from_vector<uint64_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Negative integer -1-0x00..-1-0x17 (-1..-24)
|
|
||||||
case 0x20:
|
|
||||||
case 0x21:
|
|
||||||
case 0x22:
|
|
||||||
case 0x23:
|
|
||||||
case 0x24:
|
|
||||||
case 0x25:
|
|
||||||
case 0x26:
|
|
||||||
case 0x27:
|
|
||||||
case 0x28:
|
|
||||||
case 0x29:
|
|
||||||
case 0x2a:
|
|
||||||
case 0x2b:
|
|
||||||
case 0x2c:
|
|
||||||
case 0x2d:
|
|
||||||
case 0x2e:
|
|
||||||
case 0x2f:
|
|
||||||
case 0x30:
|
|
||||||
case 0x31:
|
|
||||||
case 0x32:
|
|
||||||
case 0x33:
|
|
||||||
case 0x34:
|
|
||||||
case 0x35:
|
|
||||||
case 0x36:
|
|
||||||
case 0x37:
|
|
||||||
{
|
|
||||||
return static_cast<int8_t>(0x20 - 1 - v[current_idx]);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x38: // Negative integer (one-byte uint8_t follows)
|
|
||||||
{
|
|
||||||
idx += 1; // skip content byte
|
|
||||||
// must be uint8_t !
|
|
||||||
return static_cast<number_integer_t>(-1) - get_from_vector<uint8_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
|
|
||||||
{
|
|
||||||
idx += 2; // skip 2 content bytes
|
|
||||||
return static_cast<number_integer_t>(-1) - get_from_vector<uint16_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x3a: // Negative integer -1-n (four-byte uint32_t follows)
|
|
||||||
{
|
|
||||||
idx += 4; // skip 4 content bytes
|
|
||||||
return static_cast<number_integer_t>(-1) - get_from_vector<uint32_t>(v, current_idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows)
|
|
||||||
{
|
|
||||||
idx += 8; // skip 8 content bytes
|
|
||||||
return static_cast<number_integer_t>(-1) - static_cast<number_integer_t>(get_from_vector<uint64_t>(v, current_idx));
|
|
||||||
}
|
|
||||||
|
|
||||||
// UTF-8 string (0x00..0x17 bytes follow)
|
|
||||||
case 0x60:
|
|
||||||
case 0x61:
|
|
||||||
case 0x62:
|
|
||||||
case 0x63:
|
|
||||||
case 0x64:
|
|
||||||
case 0x65:
|
|
||||||
case 0x66:
|
|
||||||
case 0x67:
|
|
||||||
case 0x68:
|
|
||||||
case 0x69:
|
|
||||||
case 0x6a:
|
|
||||||
case 0x6b:
|
|
||||||
case 0x6c:
|
|
||||||
case 0x6d:
|
|
||||||
case 0x6e:
|
|
||||||
case 0x6f:
|
|
||||||
case 0x70:
|
|
||||||
case 0x71:
|
|
||||||
case 0x72:
|
|
||||||
case 0x73:
|
|
||||||
case 0x74:
|
|
||||||
case 0x75:
|
|
||||||
case 0x76:
|
|
||||||
case 0x77:
|
|
||||||
{
|
|
||||||
const auto len = static_cast<size_t>(v[current_idx] - 0x60);
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
|
|
||||||
{
|
|
||||||
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 0x79: // UTF-8 string (two-byte uint16_t for n follow)
|
|
||||||
{
|
|
||||||
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 0x7a: // UTF-8 string (four-byte uint32_t for n follow)
|
|
||||||
{
|
|
||||||
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 0x7b: // UTF-8 string (eight-byte uint64_t for n follow)
|
|
||||||
{
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
|
|
||||||
const size_t offset = current_idx + 9;
|
|
||||||
idx += len + 8; // skip 8 size bytes + content bytes
|
|
||||||
check_length(v.size(), len, offset);
|
|
||||||
return std::string(reinterpret_cast<const char*>(v.data()) + offset, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x7f: // UTF-8 string (indefinite length)
|
|
||||||
{
|
|
||||||
std::string result;
|
|
||||||
while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
|
|
||||||
{
|
|
||||||
string_t s = from_cbor_internal(v, idx);
|
|
||||||
result += s;
|
|
||||||
}
|
|
||||||
// skip break byte (0xFF)
|
|
||||||
idx += 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// array (0x00..0x17 data items follow)
|
|
||||||
case 0x80:
|
|
||||||
case 0x81:
|
|
||||||
case 0x82:
|
|
||||||
case 0x83:
|
|
||||||
case 0x84:
|
|
||||||
case 0x85:
|
|
||||||
case 0x86:
|
|
||||||
case 0x87:
|
|
||||||
case 0x88:
|
|
||||||
case 0x89:
|
|
||||||
case 0x8a:
|
|
||||||
case 0x8b:
|
|
||||||
case 0x8c:
|
|
||||||
case 0x8d:
|
|
||||||
case 0x8e:
|
|
||||||
case 0x8f:
|
|
||||||
case 0x90:
|
|
||||||
case 0x91:
|
|
||||||
case 0x92:
|
|
||||||
case 0x93:
|
|
||||||
case 0x94:
|
|
||||||
case 0x95:
|
|
||||||
case 0x96:
|
|
||||||
case 0x97:
|
|
||||||
{
|
|
||||||
basic_json result = value_t::array;
|
|
||||||
const auto len = static_cast<size_t>(v[current_idx] - 0x80);
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
result.push_back(from_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x98: // array (one-byte uint8_t for n follows)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::array;
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
|
|
||||||
idx += 1; // skip 1 size byte
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
result.push_back(from_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x99: // array (two-byte uint16_t for n follow)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::array;
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint16_t>(v, current_idx));
|
|
||||||
idx += 2; // skip 4 size bytes
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
result.push_back(from_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x9a: // array (four-byte uint32_t for n follow)
|
|
||||||
{
|
|
||||||
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_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x9b: // array (eight-byte uint64_t for n follow)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::array;
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
|
|
||||||
idx += 8; // skip 8 size bytes
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
result.push_back(from_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0x9f: // array (indefinite length)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::array;
|
|
||||||
while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
|
|
||||||
{
|
|
||||||
result.push_back(from_cbor_internal(v, idx));
|
|
||||||
}
|
|
||||||
// skip break byte (0xFF)
|
|
||||||
idx += 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// map (0x00..0x17 pairs of data items follow)
|
|
||||||
case 0xa0:
|
|
||||||
case 0xa1:
|
|
||||||
case 0xa2:
|
|
||||||
case 0xa3:
|
|
||||||
case 0xa4:
|
|
||||||
case 0xa5:
|
|
||||||
case 0xa6:
|
|
||||||
case 0xa7:
|
|
||||||
case 0xa8:
|
|
||||||
case 0xa9:
|
|
||||||
case 0xaa:
|
|
||||||
case 0xab:
|
|
||||||
case 0xac:
|
|
||||||
case 0xad:
|
|
||||||
case 0xae:
|
|
||||||
case 0xaf:
|
|
||||||
case 0xb0:
|
|
||||||
case 0xb1:
|
|
||||||
case 0xb2:
|
|
||||||
case 0xb3:
|
|
||||||
case 0xb4:
|
|
||||||
case 0xb5:
|
|
||||||
case 0xb6:
|
|
||||||
case 0xb7:
|
|
||||||
{
|
|
||||||
basic_json result = value_t::object;
|
|
||||||
const auto len = static_cast<size_t>(v[current_idx] - 0xa0);
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xb8: // map (one-byte uint8_t for n follows)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::object;
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint8_t>(v, current_idx));
|
|
||||||
idx += 1; // skip 1 size byte
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xb9: // map (two-byte uint16_t for n follow)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xba: // map (four-byte uint32_t for n follow)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xbb: // map (eight-byte uint64_t for n follow)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::object;
|
|
||||||
const auto len = static_cast<size_t>(get_from_vector<uint64_t>(v, current_idx));
|
|
||||||
idx += 8; // skip 8 size bytes
|
|
||||||
for (size_t i = 0; i < len; ++i)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xbf: // map (indefinite length)
|
|
||||||
{
|
|
||||||
basic_json result = value_t::object;
|
|
||||||
while (static_cast<void>(check_length(v.size(), 1, idx)), v[idx] != 0xff)
|
|
||||||
{
|
|
||||||
cbor_expect_string(v, idx);
|
|
||||||
std::string key = from_cbor_internal(v, idx);
|
|
||||||
result[key] = from_cbor_internal(v, idx);
|
|
||||||
}
|
|
||||||
// skip break byte (0xFF)
|
|
||||||
idx += 1;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xf4: // false
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xf5: // true
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xf6: // null
|
|
||||||
{
|
|
||||||
return value_t::null;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xf9: // Half-Precision Float (two-byte IEEE 754)
|
|
||||||
{
|
|
||||||
idx += 2; // skip two content bytes
|
|
||||||
|
|
||||||
// code from RFC 7049, Appendix D, Figure 3:
|
|
||||||
// As half-precision floating-point numbers were only added to
|
|
||||||
// IEEE 754 in 2008, today's programming platforms often still
|
|
||||||
// only have limited support for them. It is very easy to
|
|
||||||
// include at least decoding support for them even without such
|
|
||||||
// support. An example of a small decoder for half-precision
|
|
||||||
// floating-point numbers in the C language is shown in Fig. 3.
|
|
||||||
check_length(v.size(), 2, current_idx + 1);
|
|
||||||
const int half = (v[current_idx + 1] << 8) + v[current_idx + 2];
|
|
||||||
const int exp = (half >> 10) & 0x1f;
|
|
||||||
const int mant = half & 0x3ff;
|
|
||||||
double val;
|
|
||||||
if (exp == 0)
|
|
||||||
{
|
|
||||||
val = std::ldexp(mant, -24);
|
|
||||||
}
|
|
||||||
else if (exp != 31)
|
|
||||||
{
|
|
||||||
val = std::ldexp(mant + 1024, exp - 25);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
val = mant == 0
|
|
||||||
? std::numeric_limits<double>::infinity()
|
|
||||||
: std::numeric_limits<double>::quiet_NaN();
|
|
||||||
}
|
|
||||||
return (half & 0x8000) != 0 ? -val : val;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xfa: // Single-Precision Float (four-byte IEEE 754)
|
|
||||||
{
|
|
||||||
// copy bytes in reverse order into the float variable
|
|
||||||
float res;
|
|
||||||
check_length(v.size(), sizeof(float), current_idx + 1);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 0xfb: // Double-Precision Float (eight-byte IEEE 754)
|
|
||||||
{
|
|
||||||
// copy bytes in reverse order into the double variable
|
|
||||||
double res;
|
|
||||||
check_length(v.size(), sizeof(double), current_idx + 1);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
default: // anything else (0xFF is handled inside the other types)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << std::hex << static_cast<int>(v[current_idx]);
|
|
||||||
JSON_THROW(parse_error::create(112, current_idx + 1, "error reading CBOR; last byte: 0x" + ss.str()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@brief create a MessagePack serialization of a given JSON value
|
@brief create a MessagePack serialization of a given JSON value
|
||||||
|
@ -9053,7 +8554,7 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@brief create a MessagePack serialization of a given JSON value
|
@brief create a CBOR serialization of a given JSON value
|
||||||
|
|
||||||
Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
|
Serializes a given JSON value @a j to a byte vector using the CBOR (Concise
|
||||||
Binary Object Representation) serialization format. CBOR is a binary
|
Binary Object Representation) serialization format. CBOR is a binary
|
||||||
|
@ -9141,100 +8642,6 @@ class basic_json
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief create a JSON value from a byte vector in CBOR format
|
|
||||||
|
|
||||||
Deserializes a given byte vector @a v to a JSON value using the CBOR
|
|
||||||
(Concise Binary Object Representation) serialization format.
|
|
||||||
|
|
||||||
The library maps CBOR types to JSON value types as follows:
|
|
||||||
|
|
||||||
CBOR type | JSON value type | first byte
|
|
||||||
---------------------- | --------------- | ----------
|
|
||||||
Integer | number_unsigned | 0x00..0x17
|
|
||||||
Unsigned integer | number_unsigned | 0x18
|
|
||||||
Unsigned integer | number_unsigned | 0x19
|
|
||||||
Unsigned integer | number_unsigned | 0x1a
|
|
||||||
Unsigned integer | number_unsigned | 0x1b
|
|
||||||
Negative integer | number_integer | 0x20..0x37
|
|
||||||
Negative integer | number_integer | 0x38
|
|
||||||
Negative integer | number_integer | 0x39
|
|
||||||
Negative integer | number_integer | 0x3a
|
|
||||||
Negative integer | number_integer | 0x3b
|
|
||||||
Negative integer | number_integer | 0x40..0x57
|
|
||||||
UTF-8 string | string | 0x60..0x77
|
|
||||||
UTF-8 string | string | 0x78
|
|
||||||
UTF-8 string | string | 0x79
|
|
||||||
UTF-8 string | string | 0x7a
|
|
||||||
UTF-8 string | string | 0x7b
|
|
||||||
UTF-8 string | string | 0x7f
|
|
||||||
array | array | 0x80..0x97
|
|
||||||
array | array | 0x98
|
|
||||||
array | array | 0x99
|
|
||||||
array | array | 0x9a
|
|
||||||
array | array | 0x9b
|
|
||||||
array | array | 0x9f
|
|
||||||
map | object | 0xa0..0xb7
|
|
||||||
map | object | 0xb8
|
|
||||||
map | object | 0xb9
|
|
||||||
map | object | 0xba
|
|
||||||
map | object | 0xbb
|
|
||||||
map | object | 0xbf
|
|
||||||
False | `false` | 0xf4
|
|
||||||
True | `true` | 0xf5
|
|
||||||
Nill | `null` | 0xf6
|
|
||||||
Half-Precision Float | number_float | 0xf9
|
|
||||||
Single-Precision Float | number_float | 0xfa
|
|
||||||
Double-Precision Float | number_float | 0xfb
|
|
||||||
|
|
||||||
@warning The mapping is **incomplete** in the sense that not all CBOR
|
|
||||||
types can be converted to a JSON value. The following CBOR types
|
|
||||||
are not supported and will yield parse errors (parse_error.112):
|
|
||||||
- byte strings (0x40..0x5f)
|
|
||||||
- date/time (0xc0..0xc1)
|
|
||||||
- bignum (0xc2..0xc3)
|
|
||||||
- decimal fraction (0xc4)
|
|
||||||
- bigfloat (0xc5)
|
|
||||||
- tagged items (0xc6..0xd4, 0xd8..0xdb)
|
|
||||||
- expected conversions (0xd5..0xd7)
|
|
||||||
- simple values (0xe0..0xf3, 0xf8)
|
|
||||||
- undefined (0xf7)
|
|
||||||
|
|
||||||
@warning CBOR allows map keys of any type, whereas JSON only allows
|
|
||||||
strings as keys in object values. Therefore, CBOR maps with keys
|
|
||||||
other than UTF-8 strings are rejected (parse_error.113).
|
|
||||||
|
|
||||||
@note Any CBOR output created @ref to_cbor can be successfully parsed by
|
|
||||||
@ref from_cbor.
|
|
||||||
|
|
||||||
@param[in] v a byte vector in CBOR format
|
|
||||||
@param[in] start_index the index to start reading from @a v (0 by default)
|
|
||||||
@return deserialized JSON value
|
|
||||||
|
|
||||||
@throw parse_error.110 if the given vector ends prematurely
|
|
||||||
@throw parse_error.112 if unsupported features from CBOR were
|
|
||||||
used in the given vector @a v or if the input is not valid CBOR
|
|
||||||
@throw parse_error.113 if a string was expected as map key, but not found
|
|
||||||
|
|
||||||
@complexity Linear in the size of the byte vector @a v.
|
|
||||||
|
|
||||||
@liveexample{The example shows the deserialization of a byte vector in CBOR
|
|
||||||
format to a JSON value.,from_cbor}
|
|
||||||
|
|
||||||
@sa http://cbor.io
|
|
||||||
@sa @ref to_cbor(const basic_json&) for the analogous serialization
|
|
||||||
@sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
|
|
||||||
related MessagePack format
|
|
||||||
|
|
||||||
@since version 2.0.9, parameter @a start_index since 2.1.1
|
|
||||||
*/
|
|
||||||
//static basic_json from_cbor(const std::vector<uint8_t>& v,
|
|
||||||
// const size_t start_index = 0)
|
|
||||||
//{
|
|
||||||
// size_t i = start_index;
|
|
||||||
// return from_cbor_internal(v, i);
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
///////////////////////////
|
///////////////////////////
|
||||||
|
@ -10996,6 +10403,94 @@ class basic_json
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief create a JSON value from a byte vector in CBOR format
|
||||||
|
|
||||||
|
Deserializes a given byte vector @a v to a JSON value using the CBOR
|
||||||
|
(Concise Binary Object Representation) serialization format.
|
||||||
|
|
||||||
|
The library maps CBOR types to JSON value types as follows:
|
||||||
|
|
||||||
|
CBOR type | JSON value type | first byte
|
||||||
|
---------------------- | --------------- | ----------
|
||||||
|
Integer | number_unsigned | 0x00..0x17
|
||||||
|
Unsigned integer | number_unsigned | 0x18
|
||||||
|
Unsigned integer | number_unsigned | 0x19
|
||||||
|
Unsigned integer | number_unsigned | 0x1a
|
||||||
|
Unsigned integer | number_unsigned | 0x1b
|
||||||
|
Negative integer | number_integer | 0x20..0x37
|
||||||
|
Negative integer | number_integer | 0x38
|
||||||
|
Negative integer | number_integer | 0x39
|
||||||
|
Negative integer | number_integer | 0x3a
|
||||||
|
Negative integer | number_integer | 0x3b
|
||||||
|
Negative integer | number_integer | 0x40..0x57
|
||||||
|
UTF-8 string | string | 0x60..0x77
|
||||||
|
UTF-8 string | string | 0x78
|
||||||
|
UTF-8 string | string | 0x79
|
||||||
|
UTF-8 string | string | 0x7a
|
||||||
|
UTF-8 string | string | 0x7b
|
||||||
|
UTF-8 string | string | 0x7f
|
||||||
|
array | array | 0x80..0x97
|
||||||
|
array | array | 0x98
|
||||||
|
array | array | 0x99
|
||||||
|
array | array | 0x9a
|
||||||
|
array | array | 0x9b
|
||||||
|
array | array | 0x9f
|
||||||
|
map | object | 0xa0..0xb7
|
||||||
|
map | object | 0xb8
|
||||||
|
map | object | 0xb9
|
||||||
|
map | object | 0xba
|
||||||
|
map | object | 0xbb
|
||||||
|
map | object | 0xbf
|
||||||
|
False | `false` | 0xf4
|
||||||
|
True | `true` | 0xf5
|
||||||
|
Nill | `null` | 0xf6
|
||||||
|
Half-Precision Float | number_float | 0xf9
|
||||||
|
Single-Precision Float | number_float | 0xfa
|
||||||
|
Double-Precision Float | number_float | 0xfb
|
||||||
|
|
||||||
|
@warning The mapping is **incomplete** in the sense that not all CBOR
|
||||||
|
types can be converted to a JSON value. The following CBOR types
|
||||||
|
are not supported and will yield parse errors (parse_error.112):
|
||||||
|
- byte strings (0x40..0x5f)
|
||||||
|
- date/time (0xc0..0xc1)
|
||||||
|
- bignum (0xc2..0xc3)
|
||||||
|
- decimal fraction (0xc4)
|
||||||
|
- bigfloat (0xc5)
|
||||||
|
- tagged items (0xc6..0xd4, 0xd8..0xdb)
|
||||||
|
- expected conversions (0xd5..0xd7)
|
||||||
|
- simple values (0xe0..0xf3, 0xf8)
|
||||||
|
- undefined (0xf7)
|
||||||
|
|
||||||
|
@warning CBOR allows map keys of any type, whereas JSON only allows
|
||||||
|
strings as keys in object values. Therefore, CBOR maps with keys
|
||||||
|
other than UTF-8 strings are rejected (parse_error.113).
|
||||||
|
|
||||||
|
@note Any CBOR output created @ref to_cbor can be successfully parsed by
|
||||||
|
@ref from_cbor.
|
||||||
|
|
||||||
|
@param[in] v a byte vector in CBOR format
|
||||||
|
@param[in] start_index the index to start reading from @a v (0 by default)
|
||||||
|
@return deserialized JSON value
|
||||||
|
|
||||||
|
@throw parse_error.110 if the given vector ends prematurely
|
||||||
|
@throw parse_error.112 if unsupported features from CBOR were
|
||||||
|
used in the given vector @a v or if the input is not valid CBOR
|
||||||
|
@throw parse_error.113 if a string was expected as map key, but not found
|
||||||
|
|
||||||
|
@complexity Linear in the size of the byte vector @a v.
|
||||||
|
|
||||||
|
@liveexample{The example shows the deserialization of a byte vector in CBOR
|
||||||
|
format to a JSON value.,from_cbor}
|
||||||
|
|
||||||
|
@sa http://cbor.io
|
||||||
|
@sa @ref to_cbor(const basic_json&) for the analogous serialization
|
||||||
|
@sa @ref from_msgpack(const std::vector<uint8_t>&, const size_t) for the
|
||||||
|
related MessagePack format
|
||||||
|
|
||||||
|
@since version 2.0.9, parameter @a start_index since 2.1.1
|
||||||
|
*/
|
||||||
static basic_json from_cbor(const std::vector<uint8_t>& v,
|
static basic_json from_cbor(const std::vector<uint8_t>& v,
|
||||||
const size_t start_index = 0)
|
const size_t start_index = 0)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Reference in a new issue