🚧 a lot of minor changes
- Removed unused headers. - Added override where needed. - Added description for parse_error.113 exception. - Fixed some conversion warnings. - Integrated cbor_expect_string function for CBOR maps. - Added documentation on the supported CBOR/MessagePack features. - Added test to check all initial bytes for CBOR input.
This commit is contained in:
parent
483a58f625
commit
c5711f3072
10 changed files with 385 additions and 90 deletions
137
src/json.hpp
137
src/json.hpp
|
@ -32,7 +32,6 @@ SOFTWARE.
|
|||
#include <algorithm> // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <ciso646> // and, not, or
|
||||
#include <clocale> // lconv, localeconv
|
||||
#include <cmath> // isfinite, labs, ldexp, signbit
|
||||
|
@ -43,7 +42,6 @@ SOFTWARE.
|
|||
#include <forward_list> // forward_list
|
||||
#include <functional> // function, hash, less
|
||||
#include <initializer_list> // initializer_list
|
||||
#include <iomanip> // setw
|
||||
#include <iostream> // istream, ostream
|
||||
#include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
|
||||
#include <limits> // numeric_limits
|
||||
|
@ -130,7 +128,7 @@ class exception : public std::exception
|
|||
{}
|
||||
|
||||
/// returns the explanatory string
|
||||
virtual const char* what() const noexcept
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return what_arg.c_str();
|
||||
}
|
||||
|
@ -174,7 +172,7 @@ json.exception.parse_error.109 | parse error: array index 'one' is not a number
|
|||
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
|
||||
json.exception.parse_error.111 | parse error: bad input stream | Parsing CBOR or MessagePack from an input stream where the [`badbit` or `failbit`](http://en.cppreference.com/w/cpp/io/ios_base/iostate) is set.
|
||||
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
|
||||
json.exception.parse_error.113 | | While parsing a map key, a value that is not a string has been read.
|
||||
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -6468,7 +6466,7 @@ class basic_json
|
|||
auto i = val.m_value.object->cbegin();
|
||||
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
||||
{
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
o.put('\"');
|
||||
dump_escaped(i->first);
|
||||
o.write("\": ", 3);
|
||||
|
@ -6478,14 +6476,14 @@ class basic_json
|
|||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
o.put('\"');
|
||||
dump_escaped(i->first);
|
||||
o.write("\": ", 3);
|
||||
dump(i->second, true, indent_step, new_indent);
|
||||
|
||||
o.put('\n');
|
||||
o.write(indent_string.c_str(), current_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
||||
o.put('}');
|
||||
}
|
||||
else
|
||||
|
@ -6538,18 +6536,18 @@ class basic_json
|
|||
// first n-1 elements
|
||||
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
||||
{
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
dump(*i, true, indent_step, new_indent);
|
||||
o.write(",\n", 2);
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
dump(val.m_value.array->back(), true, indent_step, new_indent);
|
||||
|
||||
o.put('\n');
|
||||
o.write(indent_string.c_str(), current_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
||||
o.put(']');
|
||||
}
|
||||
else
|
||||
|
@ -7848,7 +7846,7 @@ class basic_json
|
|||
const auto N = j.m_value.string->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0x60 + static_cast<uint8_t>(N)); // 1 byte for string + size
|
||||
v.push_back(static_cast<uint8_t>(0x60 + N)); // 1 byte for string + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -7884,7 +7882,7 @@ class basic_json
|
|||
const auto N = j.m_value.array->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0x80 + static_cast<uint8_t>(N)); // 1 byte for array + size
|
||||
v.push_back(static_cast<uint8_t>(0x80 + N)); // 1 byte for array + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -7922,7 +7920,7 @@ class basic_json
|
|||
const auto N = j.m_value.object->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0xa0 + static_cast<uint8_t>(N)); // 1 byte for object + size
|
||||
v.push_back(static_cast<uint8_t>(0xa0 + N)); // 1 byte for object + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -8653,6 +8651,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8666,6 +8665,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8679,6 +8679,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8692,6 +8693,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8705,6 +8707,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8716,6 +8719,7 @@ class basic_json
|
|||
basic_json result = value_t::object;
|
||||
while (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);
|
||||
}
|
||||
|
@ -8864,6 +8868,9 @@ class basic_json
|
|||
- float 32 (0xca)
|
||||
- fixext 1 - fixext 16 (0xd4..0xd8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
|
||||
@param[in] j JSON value to serialize
|
||||
@return MessagePack serialization as byte vector
|
||||
|
||||
|
@ -8892,6 +8899,46 @@ class basic_json
|
|||
Deserializes a given byte vector @a v to a JSON value using the MessagePack
|
||||
serialization format.
|
||||
|
||||
The library maps MessagePack types to JSON value types as follows:
|
||||
|
||||
MessagePack type | JSON value type | first byte
|
||||
---------------- | --------------- | ----------
|
||||
positive fixint | number_unsigned | 0x00..0x7f
|
||||
fixmap | object | 0x80..0x8f
|
||||
fixarray | array | 0x90..0x9f
|
||||
fixstr | string | 0xa0..0xbf
|
||||
nil | `null` | 0xc0
|
||||
false | `false` | 0xc2
|
||||
true | `true` | 0xc3
|
||||
float 32 | number_float | 0xca
|
||||
float 64 | number_float | 0xcb
|
||||
uint 8 | number_unsigned | 0xcc
|
||||
uint 16 | number_unsigned | 0xcd
|
||||
uint 32 | number_unsigned | 0xce
|
||||
uint 64 | number_unsigned | 0xcf
|
||||
int 8 | number_integer | 0xd0
|
||||
int 16 | number_integer | 0xd1
|
||||
int 32 | number_integer | 0xd2
|
||||
int 64 | number_integer | 0xd3
|
||||
str 8 | string | 0xd9
|
||||
str 16 | string | 0xda
|
||||
str 32 | string | 0xdb
|
||||
array 16 | array | 0xdc
|
||||
array 32 | array | 0xdd
|
||||
map 16 | object | 0xde
|
||||
map 32 | object | 0xdf
|
||||
negative fixint | number_integer | 0xe0-0xff
|
||||
|
||||
@warning The mapping is **incomplete** in the sense that not all
|
||||
MessagePack types can be converted to a JSON value. The following
|
||||
MessagePack types are not supported and will yield parse errors:
|
||||
- bin 8 - bin 32 (0xc4..0xc6)
|
||||
- ext 8 - ext 32 (0xc7..0xc9)
|
||||
- fixext 1 - fixext 16 (0xd4..0xd8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
|
||||
@param[in] v a byte vector in MessagePack format
|
||||
@param[in] start_index the index to start reading from @a v (0 by default)
|
||||
@return deserialized JSON value
|
||||
|
@ -8899,6 +8946,7 @@ class basic_json
|
|||
@throw parse_error.110 if the given vector ends prematurely
|
||||
@throw parse_error.112 if unsupported features from MessagePack were
|
||||
used in the given vector @a v or if the input is not valid MessagePack
|
||||
@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.
|
||||
|
||||
|
@ -9014,6 +9062,66 @@ class basic_json
|
|||
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
|
||||
|
@ -9021,6 +9129,7 @@ class basic_json
|
|||
@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.
|
||||
|
||||
|
@ -12423,7 +12532,7 @@ basic_json_parser_74:
|
|||
reference_token.end(),
|
||||
[](const char x)
|
||||
{
|
||||
return std::isdigit(x);
|
||||
return (x >= '0' and x <= '9');
|
||||
});
|
||||
|
||||
// change value to array for numbers or "-" or to object
|
||||
|
|
|
@ -32,7 +32,6 @@ SOFTWARE.
|
|||
#include <algorithm> // all_of, copy, fill, find, for_each, none_of, remove, reverse, transform
|
||||
#include <array> // array
|
||||
#include <cassert> // assert
|
||||
#include <cctype> // isdigit
|
||||
#include <ciso646> // and, not, or
|
||||
#include <clocale> // lconv, localeconv
|
||||
#include <cmath> // isfinite, labs, ldexp, signbit
|
||||
|
@ -43,7 +42,6 @@ SOFTWARE.
|
|||
#include <forward_list> // forward_list
|
||||
#include <functional> // function, hash, less
|
||||
#include <initializer_list> // initializer_list
|
||||
#include <iomanip> // setw
|
||||
#include <iostream> // istream, ostream
|
||||
#include <iterator> // advance, begin, back_inserter, bidirectional_iterator_tag, distance, end, inserter, iterator, iterator_traits, next, random_access_iterator_tag, reverse_iterator
|
||||
#include <limits> // numeric_limits
|
||||
|
@ -130,7 +128,7 @@ class exception : public std::exception
|
|||
{}
|
||||
|
||||
/// returns the explanatory string
|
||||
virtual const char* what() const noexcept
|
||||
virtual const char* what() const noexcept override
|
||||
{
|
||||
return what_arg.c_str();
|
||||
}
|
||||
|
@ -174,7 +172,7 @@ json.exception.parse_error.109 | parse error: array index 'one' is not a number
|
|||
json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read.
|
||||
json.exception.parse_error.111 | parse error: bad input stream | Parsing CBOR or MessagePack from an input stream where the [`badbit` or `failbit`](http://en.cppreference.com/w/cpp/io/ios_base/iostate) is set.
|
||||
json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xf8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read.
|
||||
json.exception.parse_error.113 | | While parsing a map key, a value that is not a string has been read.
|
||||
json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read.
|
||||
|
||||
@since version 3.0.0
|
||||
*/
|
||||
|
@ -6468,7 +6466,7 @@ class basic_json
|
|||
auto i = val.m_value.object->cbegin();
|
||||
for (size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
|
||||
{
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
o.put('\"');
|
||||
dump_escaped(i->first);
|
||||
o.write("\": ", 3);
|
||||
|
@ -6478,14 +6476,14 @@ class basic_json
|
|||
|
||||
// last element
|
||||
assert(i != val.m_value.object->cend());
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
o.put('\"');
|
||||
dump_escaped(i->first);
|
||||
o.write("\": ", 3);
|
||||
dump(i->second, true, indent_step, new_indent);
|
||||
|
||||
o.put('\n');
|
||||
o.write(indent_string.c_str(), current_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
||||
o.put('}');
|
||||
}
|
||||
else
|
||||
|
@ -6538,18 +6536,18 @@ class basic_json
|
|||
// first n-1 elements
|
||||
for (auto i = val.m_value.array->cbegin(); i != val.m_value.array->cend() - 1; ++i)
|
||||
{
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
dump(*i, true, indent_step, new_indent);
|
||||
o.write(",\n", 2);
|
||||
}
|
||||
|
||||
// last element
|
||||
assert(not val.m_value.array->empty());
|
||||
o.write(indent_string.c_str(), new_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(new_indent));
|
||||
dump(val.m_value.array->back(), true, indent_step, new_indent);
|
||||
|
||||
o.put('\n');
|
||||
o.write(indent_string.c_str(), current_indent);
|
||||
o.write(indent_string.c_str(), static_cast<std::streamsize>(current_indent));
|
||||
o.put(']');
|
||||
}
|
||||
else
|
||||
|
@ -7848,7 +7846,7 @@ class basic_json
|
|||
const auto N = j.m_value.string->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0x60 + static_cast<uint8_t>(N)); // 1 byte for string + size
|
||||
v.push_back(static_cast<uint8_t>(0x60 + N)); // 1 byte for string + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -7884,7 +7882,7 @@ class basic_json
|
|||
const auto N = j.m_value.array->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0x80 + static_cast<uint8_t>(N)); // 1 byte for array + size
|
||||
v.push_back(static_cast<uint8_t>(0x80 + N)); // 1 byte for array + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -7922,7 +7920,7 @@ class basic_json
|
|||
const auto N = j.m_value.object->size();
|
||||
if (N <= 0x17)
|
||||
{
|
||||
v.push_back(0xa0 + static_cast<uint8_t>(N)); // 1 byte for object + size
|
||||
v.push_back(static_cast<uint8_t>(0xa0 + N)); // 1 byte for object + size
|
||||
}
|
||||
else if (N <= 0xff)
|
||||
{
|
||||
|
@ -8653,6 +8651,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8666,6 +8665,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8679,6 +8679,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8692,6 +8693,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8705,6 +8707,7 @@ class basic_json
|
|||
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);
|
||||
}
|
||||
|
@ -8716,6 +8719,7 @@ class basic_json
|
|||
basic_json result = value_t::object;
|
||||
while (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);
|
||||
}
|
||||
|
@ -8864,6 +8868,9 @@ class basic_json
|
|||
- float 32 (0xca)
|
||||
- fixext 1 - fixext 16 (0xd4..0xd8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
|
||||
@param[in] j JSON value to serialize
|
||||
@return MessagePack serialization as byte vector
|
||||
|
||||
|
@ -8892,6 +8899,46 @@ class basic_json
|
|||
Deserializes a given byte vector @a v to a JSON value using the MessagePack
|
||||
serialization format.
|
||||
|
||||
The library maps MessagePack types to JSON value types as follows:
|
||||
|
||||
MessagePack type | JSON value type | first byte
|
||||
---------------- | --------------- | ----------
|
||||
positive fixint | number_unsigned | 0x00..0x7f
|
||||
fixmap | object | 0x80..0x8f
|
||||
fixarray | array | 0x90..0x9f
|
||||
fixstr | string | 0xa0..0xbf
|
||||
nil | `null` | 0xc0
|
||||
false | `false` | 0xc2
|
||||
true | `true` | 0xc3
|
||||
float 32 | number_float | 0xca
|
||||
float 64 | number_float | 0xcb
|
||||
uint 8 | number_unsigned | 0xcc
|
||||
uint 16 | number_unsigned | 0xcd
|
||||
uint 32 | number_unsigned | 0xce
|
||||
uint 64 | number_unsigned | 0xcf
|
||||
int 8 | number_integer | 0xd0
|
||||
int 16 | number_integer | 0xd1
|
||||
int 32 | number_integer | 0xd2
|
||||
int 64 | number_integer | 0xd3
|
||||
str 8 | string | 0xd9
|
||||
str 16 | string | 0xda
|
||||
str 32 | string | 0xdb
|
||||
array 16 | array | 0xdc
|
||||
array 32 | array | 0xdd
|
||||
map 16 | object | 0xde
|
||||
map 32 | object | 0xdf
|
||||
negative fixint | number_integer | 0xe0-0xff
|
||||
|
||||
@warning The mapping is **incomplete** in the sense that not all
|
||||
MessagePack types can be converted to a JSON value. The following
|
||||
MessagePack types are not supported and will yield parse errors:
|
||||
- bin 8 - bin 32 (0xc4..0xc6)
|
||||
- ext 8 - ext 32 (0xc7..0xc9)
|
||||
- fixext 1 - fixext 16 (0xd4..0xd8)
|
||||
|
||||
@note Any MessagePack output created @ref to_msgpack can be successfully
|
||||
parsed by @ref from_msgpack.
|
||||
|
||||
@param[in] v a byte vector in MessagePack format
|
||||
@param[in] start_index the index to start reading from @a v (0 by default)
|
||||
@return deserialized JSON value
|
||||
|
@ -8899,6 +8946,7 @@ class basic_json
|
|||
@throw parse_error.110 if the given vector ends prematurely
|
||||
@throw parse_error.112 if unsupported features from MessagePack were
|
||||
used in the given vector @a v or if the input is not valid MessagePack
|
||||
@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.
|
||||
|
||||
|
@ -9014,6 +9062,66 @@ class basic_json
|
|||
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
|
||||
|
@ -9021,6 +9129,7 @@ class basic_json
|
|||
@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.
|
||||
|
||||
|
@ -11456,7 +11565,7 @@ class basic_json
|
|||
reference_token.end(),
|
||||
[](const char x)
|
||||
{
|
||||
return std::isdigit(x);
|
||||
return (x >= '0' and x <= '9');
|
||||
});
|
||||
|
||||
// change value to array for numbers or "-" or to object
|
||||
|
|
|
@ -130,14 +130,14 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x3b);
|
||||
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
|
||||
(static_cast<uint64_t>(result[2]) << 060) +
|
||||
(static_cast<uint64_t>(result[3]) << 050) +
|
||||
(static_cast<uint64_t>(result[4]) << 040) +
|
||||
(static_cast<uint64_t>(result[5]) << 030) +
|
||||
(static_cast<uint64_t>(result[6]) << 020) +
|
||||
(static_cast<uint64_t>(result[7]) << 010) +
|
||||
static_cast<uint64_t>(result[8]));
|
||||
static_cast<uint64_t>(result[8]);
|
||||
CHECK(restored == positive);
|
||||
CHECK(-1 - static_cast<int64_t>(restored) == i);
|
||||
|
||||
|
@ -182,10 +182,10 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x3a);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == positive);
|
||||
CHECK(-1ll - restored == i);
|
||||
|
||||
|
@ -220,7 +220,7 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x39);
|
||||
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
|
||||
CHECK(restored == positive);
|
||||
CHECK(-1 - restored == i);
|
||||
|
||||
|
@ -289,7 +289,7 @@ TEST_CASE("CBOR")
|
|||
|
||||
// create expected byte vector
|
||||
std::vector<uint8_t> expected;
|
||||
expected.push_back(0x20 - 1 - static_cast<uint8_t>(i));
|
||||
expected.push_back(static_cast<uint8_t>(0x20 - 1 - static_cast<uint8_t>(i)));
|
||||
|
||||
// compare result + size
|
||||
const auto result = json::to_cbor(j);
|
||||
|
@ -392,7 +392,7 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x19);
|
||||
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -431,10 +431,10 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x1a);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -477,14 +477,14 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x1b);
|
||||
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
|
||||
(static_cast<uint64_t>(result[2]) << 060) +
|
||||
(static_cast<uint64_t>(result[3]) << 050) +
|
||||
(static_cast<uint64_t>(result[4]) << 040) +
|
||||
(static_cast<uint64_t>(result[5]) << 030) +
|
||||
(static_cast<uint64_t>(result[6]) << 020) +
|
||||
(static_cast<uint64_t>(result[7]) << 010) +
|
||||
static_cast<uint64_t>(result[8]));
|
||||
static_cast<uint64_t>(result[8]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -616,7 +616,7 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x19);
|
||||
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -654,10 +654,10 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x1a);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -699,14 +699,14 @@ TEST_CASE("CBOR")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0x1b);
|
||||
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
|
||||
(static_cast<uint64_t>(result[2]) << 060) +
|
||||
(static_cast<uint64_t>(result[3]) << 050) +
|
||||
(static_cast<uint64_t>(result[4]) << 040) +
|
||||
(static_cast<uint64_t>(result[5]) << 030) +
|
||||
(static_cast<uint64_t>(result[6]) << 020) +
|
||||
(static_cast<uint64_t>(result[7]) << 010) +
|
||||
static_cast<uint64_t>(result[8]));
|
||||
static_cast<uint64_t>(result[8]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -1538,6 +1538,83 @@ TEST_CASE("CBOR roundtrips", "[hide]")
|
|||
}
|
||||
}
|
||||
|
||||
TEST_CASE("all first bytes", "[!throws]")
|
||||
{
|
||||
// these bytes will fail immediately with exception parse_error.112
|
||||
std::set<uint8_t> unsupported =
|
||||
{
|
||||
//// types not supported by this library
|
||||
|
||||
// byte strings
|
||||
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
|
||||
0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f,
|
||||
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
|
||||
// byte strings
|
||||
0x58, 0x59, 0x5a, 0x5b, 0x5f,
|
||||
// date/time
|
||||
0xc0, 0xc1,
|
||||
// bignum
|
||||
0xc2, 0xc3,
|
||||
// decimal fracion
|
||||
0xc4,
|
||||
// bigfloat
|
||||
0xc5,
|
||||
// tagged item
|
||||
0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd,
|
||||
0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd8,
|
||||
0xd9, 0xda, 0xdb,
|
||||
// expected conversion
|
||||
0xd5, 0xd6, 0xd7,
|
||||
// simple value
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xef, 0xf0,
|
||||
0xf1, 0xf2, 0xf3,
|
||||
0xf8,
|
||||
// undefined
|
||||
0xf7,
|
||||
|
||||
//// bytes not specified by CBOR
|
||||
|
||||
0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0x3c, 0x3d, 0x3e, 0x3f,
|
||||
0x5c, 0x5d, 0x5e,
|
||||
0x7c, 0x7d, 0x7e,
|
||||
0x9c, 0x9d, 0x9e,
|
||||
0xbc, 0xbd, 0xbe,
|
||||
0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xee,
|
||||
0xfc, 0xfe, 0xfd,
|
||||
|
||||
/// break cannot be the first byte
|
||||
|
||||
0xff
|
||||
};
|
||||
|
||||
for (auto i = 0; i < 256; ++i)
|
||||
{
|
||||
const auto byte = static_cast<uint8_t>(i);
|
||||
|
||||
try
|
||||
{
|
||||
json::from_cbor({byte});
|
||||
}
|
||||
catch (const json::parse_error& e)
|
||||
{
|
||||
// check that parse_error.112 is only thrown if the
|
||||
// first byte is in the unsupported set
|
||||
CAPTURE(e.what());
|
||||
if (std::find(unsupported.begin(), unsupported.end(), byte) != unsupported.end())
|
||||
{
|
||||
CHECK(e.id == 112);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(e.id != 112);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("examples from RFC 7049 Appendix A")
|
||||
{
|
||||
SECTION("numbers")
|
||||
|
|
|
@ -139,7 +139,7 @@ TEST_CASE("lexer class")
|
|||
for (int c = 1; c < 128; ++c)
|
||||
{
|
||||
// create string from the ASCII code
|
||||
const auto s = std::string(1, c);
|
||||
const auto s = std::string(1, static_cast<char>(c));
|
||||
// store scan() result
|
||||
const auto res = json::lexer(reinterpret_cast<const json::lexer::lexer_char_t*>(s.c_str()),
|
||||
1).scan();
|
||||
|
|
|
@ -494,7 +494,7 @@ TEST_CASE("parser class")
|
|||
// invalid escapes
|
||||
for (int c = 1; c < 128; ++c)
|
||||
{
|
||||
auto s = std::string("\"\\") + std::string(1, c) + "\"";
|
||||
auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
|
||||
|
||||
switch (c)
|
||||
{
|
||||
|
@ -574,10 +574,10 @@ TEST_CASE("parser class")
|
|||
std::string s = "\"\\u";
|
||||
|
||||
// create a string with the iterated character at each position
|
||||
auto s1 = s + "000" + std::string(1, c) + "\"";
|
||||
auto s2 = s + "00" + std::string(1, c) + "0\"";
|
||||
auto s3 = s + "0" + std::string(1, c) + "00\"";
|
||||
auto s4 = s + std::string(1, c) + "000\"";
|
||||
auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
|
||||
auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
|
||||
auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
|
||||
auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
|
||||
|
||||
if (valid(c))
|
||||
{
|
||||
|
|
|
@ -72,8 +72,8 @@ TEST_CASE("concepts")
|
|||
// X::size_type must return an unsigned integer
|
||||
CHECK((std::is_unsigned<json::size_type>::value));
|
||||
// X::size_type can represent any non-negative value of X::difference_type
|
||||
CHECK(static_cast<size_t>(std::numeric_limits<json::difference_type>::max()) <=
|
||||
static_cast<size_t>(std::numeric_limits<json::size_type>::max()));
|
||||
CHECK(static_cast<json::size_type>(std::numeric_limits<json::difference_type>::max()) <=
|
||||
std::numeric_limits<json::size_type>::max());
|
||||
|
||||
// the expression "X u" has the post-condition "u.empty()"
|
||||
{
|
||||
|
|
|
@ -48,7 +48,7 @@ TEST_CASE("element access 1")
|
|||
CHECK(j.at(3) == json(nullptr));
|
||||
CHECK(j.at(4) == json("string"));
|
||||
CHECK(j.at(5) == json(42.23));
|
||||
CHECK(j.at(6) == json(json::object()));
|
||||
CHECK(j.at(6) == json::object());
|
||||
CHECK(j.at(7) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.at(0) == json(1));
|
||||
|
@ -57,7 +57,7 @@ TEST_CASE("element access 1")
|
|||
CHECK(j_const.at(3) == json(nullptr));
|
||||
CHECK(j_const.at(4) == json("string"));
|
||||
CHECK(j_const.at(5) == json(42.23));
|
||||
CHECK(j_const.at(6) == json(json::object()));
|
||||
CHECK(j_const.at(6) == json::object());
|
||||
CHECK(j_const.at(7) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
|
@ -171,7 +171,7 @@ TEST_CASE("element access 1")
|
|||
CHECK(j[3] == json(nullptr));
|
||||
CHECK(j[4] == json("string"));
|
||||
CHECK(j[5] == json(42.23));
|
||||
CHECK(j[6] == json(json::object()));
|
||||
CHECK(j[6] == json::object());
|
||||
CHECK(j[7] == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const[0] == json(1));
|
||||
|
@ -180,7 +180,7 @@ TEST_CASE("element access 1")
|
|||
CHECK(j_const[3] == json(nullptr));
|
||||
CHECK(j_const[4] == json("string"));
|
||||
CHECK(j_const[5] == json(42.23));
|
||||
CHECK(j_const[6] == json(json::object()));
|
||||
CHECK(j_const[6] == json::object());
|
||||
CHECK(j_const[7] == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j.at("null") == json(nullptr));
|
||||
CHECK(j.at("string") == json("hello world"));
|
||||
CHECK(j.at("floating") == json(42.23));
|
||||
CHECK(j.at("object") == json(json::object()));
|
||||
CHECK(j.at("object") == json::object());
|
||||
CHECK(j.at("array") == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.at("integer") == json(1));
|
||||
|
@ -57,7 +57,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j_const.at("null") == json(nullptr));
|
||||
CHECK(j_const.at("string") == json("hello world"));
|
||||
CHECK(j_const.at("floating") == json(42.23));
|
||||
CHECK(j_const.at("object") == json(json::object()));
|
||||
CHECK(j_const.at("object") == json::object());
|
||||
CHECK(j_const.at("array") == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
|
@ -161,7 +161,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j.value("string", std::string("bar")) == "hello world");
|
||||
CHECK(j.value("floating", 12.34) == Approx(42.23));
|
||||
CHECK(j.value("floating", 12) == 42);
|
||||
CHECK(j.value("object", json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j.value("object", json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j.value("array", json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.value("integer", 2) == 1);
|
||||
|
@ -173,7 +173,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j_const.value("string", std::string("bar")) == "hello world");
|
||||
CHECK(j_const.value("floating", 12.34) == Approx(42.23));
|
||||
CHECK(j_const.value("floating", 12) == 42);
|
||||
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j_const.value("object", json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j_const.value("array", json({10, 100})) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||
CHECK(j.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||
CHECK(j.value("/floating"_json_pointer, 12) == 42);
|
||||
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j.value("/object"_json_pointer, json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||
|
||||
CHECK(j_const.value("/integer"_json_pointer, 2) == 1);
|
||||
|
@ -310,7 +310,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j_const.value("/string"_json_pointer, std::string("bar")) == "hello world");
|
||||
CHECK(j_const.value("/floating"_json_pointer, 12.34) == Approx(42.23));
|
||||
CHECK(j_const.value("/floating"_json_pointer, 12) == 42);
|
||||
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json(json::object()));
|
||||
CHECK(j_const.value("/object"_json_pointer, json({{"foo", "bar"}})) == json::object());
|
||||
CHECK(j_const.value("/array"_json_pointer, json({10, 100})) == json({1, 2, 3}));
|
||||
}
|
||||
|
||||
|
@ -435,7 +435,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j["floating"] == json(42.23));
|
||||
CHECK(j[json::object_t::key_type("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j["object"] == json(json::object()));
|
||||
CHECK(j["object"] == json::object());
|
||||
CHECK(j[json::object_t::key_type("object")] == j["object"]);
|
||||
|
||||
CHECK(j["array"] == json({1, 2, 3}));
|
||||
|
@ -456,7 +456,7 @@ TEST_CASE("element access 2")
|
|||
CHECK(j_const["floating"] == json(42.23));
|
||||
CHECK(j_const[json::object_t::key_type("floating")] == j["floating"]);
|
||||
|
||||
CHECK(j_const["object"] == json(json::object()));
|
||||
CHECK(j_const["object"] == json::object());
|
||||
CHECK(j_const[json::object_t::key_type("object")] == j["object"]);
|
||||
|
||||
CHECK(j_const["array"] == json({1, 2, 3}));
|
||||
|
|
|
@ -203,7 +203,7 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xcd);
|
||||
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -242,10 +242,10 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xce);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -288,14 +288,14 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xcf);
|
||||
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
|
||||
(static_cast<uint64_t>(result[2]) << 060) +
|
||||
(static_cast<uint64_t>(result[3]) << 050) +
|
||||
(static_cast<uint64_t>(result[4]) << 040) +
|
||||
(static_cast<uint64_t>(result[5]) << 030) +
|
||||
(static_cast<uint64_t>(result[6]) << 020) +
|
||||
(static_cast<uint64_t>(result[7]) << 010) +
|
||||
static_cast<uint64_t>(result[8]));
|
||||
static_cast<uint64_t>(result[8]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -415,10 +415,10 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xd2);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -460,14 +460,14 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xd3);
|
||||
int64_t restored = static_cast<int64_t>((static_cast<int64_t>(result[1]) << 070) +
|
||||
int64_t restored = (static_cast<int64_t>(result[1]) << 070) +
|
||||
(static_cast<int64_t>(result[2]) << 060) +
|
||||
(static_cast<int64_t>(result[3]) << 050) +
|
||||
(static_cast<int64_t>(result[4]) << 040) +
|
||||
(static_cast<int64_t>(result[5]) << 030) +
|
||||
(static_cast<int64_t>(result[6]) << 020) +
|
||||
(static_cast<int64_t>(result[7]) << 010) +
|
||||
static_cast<int64_t>(result[8]));
|
||||
static_cast<int64_t>(result[8]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -564,7 +564,7 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xcd);
|
||||
uint16_t restored = static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]);
|
||||
uint16_t restored = static_cast<uint16_t>(static_cast<uint8_t>(result[1]) * 256 + static_cast<uint8_t>(result[2]));
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -602,10 +602,10 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xce);
|
||||
uint32_t restored = static_cast<uint32_t>((static_cast<uint32_t>(result[1]) << 030) +
|
||||
uint32_t restored = (static_cast<uint32_t>(result[1]) << 030) +
|
||||
(static_cast<uint32_t>(result[2]) << 020) +
|
||||
(static_cast<uint32_t>(result[3]) << 010) +
|
||||
static_cast<uint32_t>(result[4]));
|
||||
static_cast<uint32_t>(result[4]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
@ -647,14 +647,14 @@ TEST_CASE("MessagePack")
|
|||
|
||||
// check individual bytes
|
||||
CHECK(result[0] == 0xcf);
|
||||
uint64_t restored = static_cast<uint64_t>((static_cast<uint64_t>(result[1]) << 070) +
|
||||
uint64_t restored = (static_cast<uint64_t>(result[1]) << 070) +
|
||||
(static_cast<uint64_t>(result[2]) << 060) +
|
||||
(static_cast<uint64_t>(result[3]) << 050) +
|
||||
(static_cast<uint64_t>(result[4]) << 040) +
|
||||
(static_cast<uint64_t>(result[5]) << 030) +
|
||||
(static_cast<uint64_t>(result[6]) << 020) +
|
||||
(static_cast<uint64_t>(result[7]) << 010) +
|
||||
static_cast<uint64_t>(result[8]));
|
||||
static_cast<uint64_t>(result[8]);
|
||||
CHECK(restored == i);
|
||||
|
||||
// roundtrip
|
||||
|
|
|
@ -412,17 +412,17 @@ TEST_CASE("regression tests")
|
|||
class CommaDecimalSeparator : public std::numpunct<char>
|
||||
{
|
||||
protected:
|
||||
char do_decimal_point() const
|
||||
char do_decimal_point() const override
|
||||
{
|
||||
return ',';
|
||||
}
|
||||
|
||||
char do_thousands_sep() const
|
||||
char do_thousands_sep() const override
|
||||
{
|
||||
return '.';
|
||||
}
|
||||
|
||||
std::string do_grouping() const
|
||||
std::string do_grouping() const override
|
||||
{
|
||||
return "\03";
|
||||
}
|
||||
|
@ -755,7 +755,7 @@ TEST_CASE("regression tests")
|
|||
};
|
||||
CHECK_THROWS_AS(json::from_cbor(vec), json::parse_error);
|
||||
CHECK_THROWS_WITH(json::from_cbor(vec),
|
||||
"[json.exception.parse_error.110] parse error at 137: cannot read 1 bytes from vector");
|
||||
"[json.exception.parse_error.113] parse error at 2: expected a CBOR string; last byte: 0x98");
|
||||
|
||||
// related test case: nonempty UTF-8 string (indefinite length)
|
||||
std::vector<uint8_t> vec1 {0x7f, 0x61, 0x61};
|
||||
|
@ -808,7 +808,7 @@ TEST_CASE("regression tests")
|
|||
};
|
||||
CHECK_THROWS_AS(json::from_cbor(vec1), json::parse_error);
|
||||
CHECK_THROWS_WITH(json::from_cbor(vec1),
|
||||
"[json.exception.parse_error.110] parse error at 49: cannot read 4 bytes from vector");
|
||||
"[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xb4");
|
||||
|
||||
// related test case: double-precision
|
||||
std::vector<uint8_t> vec2
|
||||
|
@ -822,7 +822,7 @@ TEST_CASE("regression tests")
|
|||
};
|
||||
CHECK_THROWS_AS(json::from_cbor(vec2), json::parse_error);
|
||||
CHECK_THROWS_WITH(json::from_cbor(vec2),
|
||||
"[json.exception.parse_error.110] parse error at 49: cannot read 8 bytes from vector");
|
||||
"[json.exception.parse_error.113] parse error at 13: expected a CBOR string; last byte: 0xb4");
|
||||
}
|
||||
|
||||
SECTION("issue #452 - Heap-buffer-overflow (OSS-Fuzz issue 585)")
|
||||
|
|
Loading…
Reference in a new issue