Merge fe24dae377 into b2306145e1
This commit is contained in:
commit
ff29547a7f
@ -237,6 +237,23 @@ class out_of_range : public exception
|
||||
out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
};
|
||||
|
||||
/// @brief exception indicating other library errors
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/other_error/
|
||||
class not_implemented : public exception
|
||||
{
|
||||
public:
|
||||
template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
|
||||
static not_implemented create(int id_, const std::string& what_arg, BasicJsonContext context)
|
||||
{
|
||||
std::string w = concat(exception::name("not_implemented", id_), exception::diagnostics(context), what_arg);
|
||||
return {id_, w.c_str()};
|
||||
}
|
||||
|
||||
private:
|
||||
JSON_HEDLEY_NON_NULL(3)
|
||||
not_implemented(int id_, const char* what_arg) : exception(id_, what_arg) {}
|
||||
};
|
||||
|
||||
/// @brief exception indicating other library errors
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/other_error/
|
||||
class other_error : public exception
|
||||
|
||||
@ -1183,7 +1183,7 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
return sax->end_object();
|
||||
return true;
|
||||
}
|
||||
|
||||
/////////////
|
||||
@ -1349,7 +1349,11 @@ class binary_reader
|
||||
case 0x8D:
|
||||
case 0x8E:
|
||||
case 0x8F:
|
||||
return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
|
||||
{
|
||||
const auto len = conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu);
|
||||
return sax->start_object(len) && get_msgpack_object(len) && sax->end_object();
|
||||
|
||||
}
|
||||
|
||||
// fixarray
|
||||
case 0x90:
|
||||
@ -1368,7 +1372,16 @@ class binary_reader
|
||||
case 0x9D:
|
||||
case 0x9E:
|
||||
case 0x9F:
|
||||
return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
|
||||
{
|
||||
const auto len = conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu);
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
sax->start_array(len)
|
||||
&&
|
||||
get_msgpack_array(len)
|
||||
&&
|
||||
sax->end_array()
|
||||
);
|
||||
}
|
||||
|
||||
// fixstr
|
||||
case 0xA0:
|
||||
@ -1499,25 +1512,58 @@ class binary_reader
|
||||
case 0xDC: // array 16
|
||||
{
|
||||
std::uint16_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_array(static_cast<std::size_t>(len))
|
||||
&&
|
||||
get_msgpack_array(static_cast<std::size_t>(len))
|
||||
&&
|
||||
sax->end_array()
|
||||
);
|
||||
}
|
||||
|
||||
case 0xDD: // array 32
|
||||
{
|
||||
std::uint32_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_array(conditional_static_cast<std::size_t>(len))
|
||||
&&
|
||||
get_msgpack_array(conditional_static_cast<std::size_t>(len))
|
||||
&&
|
||||
sax->end_array()
|
||||
);
|
||||
}
|
||||
|
||||
case 0xDE: // map 16
|
||||
{
|
||||
std::uint16_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
|
||||
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_object(len)
|
||||
&&
|
||||
get_msgpack_object(static_cast<std::size_t>(len))
|
||||
&&
|
||||
sax->end_object()
|
||||
);
|
||||
}
|
||||
|
||||
case 0xDF: // map 32
|
||||
{
|
||||
std::uint32_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_object(len)
|
||||
&&
|
||||
get_msgpack_object(conditional_static_cast<std::size_t>(len))
|
||||
&&
|
||||
sax->end_object()
|
||||
);
|
||||
}
|
||||
|
||||
// negative fixint
|
||||
@ -1770,11 +1816,6 @@ class binary_reader
|
||||
*/
|
||||
bool get_msgpack_array(const std::size_t len)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::size_t i = 0; i < len; ++i)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
|
||||
@ -1783,7 +1824,7 @@ class binary_reader
|
||||
}
|
||||
}
|
||||
|
||||
return sax->end_array();
|
||||
return true;
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -1792,28 +1833,438 @@ class binary_reader
|
||||
*/
|
||||
bool get_msgpack_object(const std::size_t len)
|
||||
{
|
||||
if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string_t key;
|
||||
string_t recycle_string;
|
||||
|
||||
for (std::size_t i = 0; i < len; ++i)
|
||||
{
|
||||
get();
|
||||
if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
|
||||
if (JSON_HEDLEY_UNLIKELY(
|
||||
!(
|
||||
get_msgpack_object_key(recycle_string, detail::is_sax_msgpack<SAX, BasicJsonType>())
|
||||
&&
|
||||
parse_msgpack_internal()
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
key.clear();
|
||||
recycle_string.clear();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return sax->end_object();
|
||||
// /*!
|
||||
// @param[in] len the length of the object
|
||||
// @param[in] full_msgpack_support is full msgpack protocoll suppored by sax
|
||||
// @return whether object creation completed
|
||||
// */
|
||||
bool get_msgpack_object_key(string_t& recycle_string, std::false_type)
|
||||
{
|
||||
get();
|
||||
return JSON_HEDLEY_LIKELY(get_msgpack_string(recycle_string) && sax->key(recycle_string));
|
||||
}
|
||||
|
||||
// /*!
|
||||
// @param[in] len the length of the object
|
||||
// @param[in] full_msgpack_support is full msgpack protocoll suppored by sax
|
||||
// @return whether object creation completed
|
||||
// */
|
||||
bool get_msgpack_object_key(string_t& recycle_string, std::true_type)
|
||||
{
|
||||
switch (get())
|
||||
{
|
||||
// EOF
|
||||
case std::char_traits<char_type>::eof():
|
||||
{
|
||||
return unexpect_eof(input_format_t::msgpack, "key");
|
||||
}
|
||||
|
||||
// positive fixint
|
||||
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:
|
||||
case 0x18:
|
||||
case 0x19:
|
||||
case 0x1A:
|
||||
case 0x1B:
|
||||
case 0x1C:
|
||||
case 0x1D:
|
||||
case 0x1E:
|
||||
case 0x1F:
|
||||
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:
|
||||
case 0x38:
|
||||
case 0x39:
|
||||
case 0x3A:
|
||||
case 0x3B:
|
||||
case 0x3C:
|
||||
case 0x3D:
|
||||
case 0x3E:
|
||||
case 0x3F:
|
||||
case 0x40:
|
||||
case 0x41:
|
||||
case 0x42:
|
||||
case 0x43:
|
||||
case 0x44:
|
||||
case 0x45:
|
||||
case 0x46:
|
||||
case 0x47:
|
||||
case 0x48:
|
||||
case 0x49:
|
||||
case 0x4A:
|
||||
case 0x4B:
|
||||
case 0x4C:
|
||||
case 0x4D:
|
||||
case 0x4E:
|
||||
case 0x4F:
|
||||
case 0x50:
|
||||
case 0x51:
|
||||
case 0x52:
|
||||
case 0x53:
|
||||
case 0x54:
|
||||
case 0x55:
|
||||
case 0x56:
|
||||
case 0x57:
|
||||
case 0x58:
|
||||
case 0x59:
|
||||
case 0x5A:
|
||||
case 0x5B:
|
||||
case 0x5C:
|
||||
case 0x5D:
|
||||
case 0x5E:
|
||||
case 0x5F:
|
||||
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:
|
||||
case 0x78:
|
||||
case 0x79:
|
||||
case 0x7A:
|
||||
case 0x7B:
|
||||
case 0x7C:
|
||||
case 0x7D:
|
||||
case 0x7E:
|
||||
case 0x7F:
|
||||
return JSON_HEDLEY_LIKELY(sax->key_unsigned(static_cast<number_unsigned_t>(current) ) );
|
||||
|
||||
// fixmap
|
||||
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:
|
||||
{
|
||||
const auto len = static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu);
|
||||
return JSON_HEDLEY_LIKELY( sax->start_key_object(len) && get_msgpack_object() && sax->end_key_object() );
|
||||
}
|
||||
|
||||
// fixarray
|
||||
case 0x90:
|
||||
case 0x91:
|
||||
case 0x92:
|
||||
case 0x93:
|
||||
case 0x94:
|
||||
case 0x95:
|
||||
case 0x96:
|
||||
case 0x97:
|
||||
case 0x98:
|
||||
case 0x99:
|
||||
case 0x9A:
|
||||
case 0x9B:
|
||||
case 0x9C:
|
||||
case 0x9D:
|
||||
case 0x9E:
|
||||
case 0x9F:
|
||||
{
|
||||
const auto len = static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu);
|
||||
return sax->start_key_array(len) && get_msgpack_array(len) && sax->end_key_array();
|
||||
}
|
||||
|
||||
// fixstr
|
||||
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:
|
||||
case 0xB8:
|
||||
case 0xB9:
|
||||
case 0xBA:
|
||||
case 0xBB:
|
||||
case 0xBC:
|
||||
case 0xBD:
|
||||
case 0xBE:
|
||||
case 0xBF:
|
||||
case 0xD9: // str 8
|
||||
case 0xDA: // str 16
|
||||
case 0xDB: // str 32
|
||||
{
|
||||
return JSON_HEDLEY_LIKELY( get_msgpack_string(recycle_string) && sax->key(recycle_string) );
|
||||
}
|
||||
|
||||
case 0xC0: // nil
|
||||
return JSON_HEDLEY_LIKELY( sax->key_null() );
|
||||
|
||||
case 0xC2: // false
|
||||
return JSON_HEDLEY_LIKELY( sax->key_boolean(false) );
|
||||
|
||||
case 0xC3: // true
|
||||
return JSON_HEDLEY_LIKELY( sax->key_boolean(true) );
|
||||
|
||||
case 0xC4: // bin 8
|
||||
case 0xC5: // bin 16
|
||||
case 0xC6: // bin 32
|
||||
case 0xC7: // ext 8
|
||||
case 0xC8: // ext 16
|
||||
case 0xC9: // ext 32
|
||||
case 0xD4: // fixext 1
|
||||
case 0xD5: // fixext 2
|
||||
case 0xD6: // fixext 4
|
||||
case 0xD7: // fixext 8
|
||||
case 0xD8: // fixext 16
|
||||
{
|
||||
binary_t b;
|
||||
return get_msgpack_binary(b) && sax->key_binary(b);
|
||||
}
|
||||
|
||||
case 0xCA: // float 32
|
||||
{
|
||||
float number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_float(static_cast<number_float_t>(number), "") );
|
||||
}
|
||||
|
||||
case 0xCB: // float 64
|
||||
{
|
||||
double number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_float(static_cast<number_float_t>(number), "") );
|
||||
}
|
||||
|
||||
case 0xCC: // uint 8
|
||||
{
|
||||
std::uint8_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_unsigned(number) );
|
||||
}
|
||||
|
||||
case 0xCD: // uint 16
|
||||
{
|
||||
std::uint16_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_unsigned(number) );
|
||||
}
|
||||
|
||||
case 0xCE: // uint 32
|
||||
{
|
||||
std::uint32_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_unsigned(number) );
|
||||
}
|
||||
|
||||
case 0xCF: // uint 64
|
||||
{
|
||||
std::uint64_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_unsigned(number) );
|
||||
}
|
||||
|
||||
case 0xD0: // int 8
|
||||
{
|
||||
std::int8_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_integer(number) );
|
||||
}
|
||||
|
||||
case 0xD1: // int 16
|
||||
{
|
||||
std::int16_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_integer(number) );
|
||||
}
|
||||
|
||||
case 0xD2: // int 32
|
||||
{
|
||||
std::int32_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_integer(number) );
|
||||
}
|
||||
|
||||
case 0xD3: // int 64
|
||||
{
|
||||
std::int64_t number{};
|
||||
return JSON_HEDLEY_LIKELY( get_number(input_format_t::msgpack, number) && sax->key_integer(number) );
|
||||
}
|
||||
|
||||
case 0xDC: // array 16
|
||||
{
|
||||
std::uint16_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && sax->start_key_array(static_cast<std::size_t>(len)) && get_msgpack_array(static_cast<std::size_t>(len)) && sax->end_key_array();
|
||||
}
|
||||
|
||||
case 0xDD: // array 32
|
||||
{
|
||||
std::uint32_t len{};
|
||||
return get_number(input_format_t::msgpack, len) && sax->start_key_array(static_cast<std::size_t>(len)) && get_msgpack_array(static_cast<std::size_t>(len)) && sax->end_key_array();
|
||||
}
|
||||
|
||||
case 0xDE: // map 16
|
||||
{
|
||||
std::uint16_t len{};
|
||||
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_key_object(len)
|
||||
&&
|
||||
get_msgpack_object()
|
||||
&&
|
||||
sax->end_key_object()
|
||||
);
|
||||
}
|
||||
|
||||
case 0xDF: // map 32
|
||||
{
|
||||
std::uint32_t len{};
|
||||
|
||||
return JSON_HEDLEY_LIKELY(
|
||||
get_number(input_format_t::msgpack, len)
|
||||
&&
|
||||
sax->start_key_object(len)
|
||||
&&
|
||||
get_msgpack_object()
|
||||
&&
|
||||
sax->end_key_object()
|
||||
);
|
||||
}
|
||||
|
||||
// negative fixint
|
||||
case 0xE0:
|
||||
case 0xE1:
|
||||
case 0xE2:
|
||||
case 0xE3:
|
||||
case 0xE4:
|
||||
case 0xE5:
|
||||
case 0xE6:
|
||||
case 0xE7:
|
||||
case 0xE8:
|
||||
case 0xE9:
|
||||
case 0xEA:
|
||||
case 0xEB:
|
||||
case 0xEC:
|
||||
case 0xED:
|
||||
case 0xEE:
|
||||
case 0xEF:
|
||||
case 0xF0:
|
||||
case 0xF1:
|
||||
case 0xF2:
|
||||
case 0xF3:
|
||||
case 0xF4:
|
||||
case 0xF5:
|
||||
case 0xF6:
|
||||
case 0xF7:
|
||||
case 0xF8:
|
||||
case 0xF9:
|
||||
case 0xFA:
|
||||
case 0xFB:
|
||||
case 0xFC:
|
||||
case 0xFD:
|
||||
case 0xFE:
|
||||
case 0xFF:
|
||||
return JSON_HEDLEY_LIKELY( sax->key_integer( static_cast<std::int8_t>(current) ) );
|
||||
|
||||
default: // anything else
|
||||
{
|
||||
auto last_token = get_token_string();
|
||||
return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
|
||||
exception_message(input_format_t::msgpack, concat("unsupported byte: 0x", last_token), "key"), nullptr));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////
|
||||
|
||||
@ -28,8 +28,9 @@ boolean return value informs the parser whether to continue processing the
|
||||
input.
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
struct json_sax
|
||||
class json_sax
|
||||
{
|
||||
public:
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
@ -142,6 +143,87 @@ struct json_sax
|
||||
virtual ~json_sax() = default;
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
class msgpack_sax : public json_sax<BasicJsonType>
|
||||
{
|
||||
public:
|
||||
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
|
||||
/*!
|
||||
@brief an object key of null value was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool key_null() = 0;
|
||||
|
||||
/*!
|
||||
@brief an object key of type bool was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool key_boolean(bool val) = 0;
|
||||
|
||||
/*!
|
||||
@brief an object key of type integer number was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool key_integer(number_integer_t val) = 0;
|
||||
|
||||
/*!
|
||||
@brief an object key of type unsigned was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool key_unsigned(number_unsigned_t val) = 0;
|
||||
|
||||
/*!
|
||||
@brief an object key of type float was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool key_float(number_float_t val, const string_t& s) = 0;
|
||||
|
||||
/*!
|
||||
@brief an object key of type binary was read
|
||||
@param[in] val binary value
|
||||
@return whether parsing should proceed
|
||||
@note It is safe to move the passed binary value.
|
||||
*/
|
||||
virtual bool key_binary(binary_t& val) = 0;
|
||||
|
||||
/*!
|
||||
@brief the beginning of a key of type array was read
|
||||
@param[in] elements number of array elements or -1 if unknown
|
||||
@return whether parsing should proceed
|
||||
@note binary formats may report the number of elements
|
||||
*/
|
||||
virtual bool start_key_array(std::size_t elements) = 0;
|
||||
|
||||
/*!
|
||||
@brief the end of a key of type array was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool end_key_array() = 0;
|
||||
|
||||
/*!
|
||||
@brief the beginning of a key of type object was read
|
||||
@param[in] elements number of object elements or -1 if unknown
|
||||
@return whether parsing should proceed
|
||||
@note binary formats may report the number of elements
|
||||
*/
|
||||
virtual bool start_key_object(std::size_t elements) = 0;
|
||||
|
||||
/*!
|
||||
@brief the end of a key of type object was read
|
||||
@return whether parsing should proceed
|
||||
*/
|
||||
virtual bool end_key_object() = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@ -158,8 +240,59 @@ constructor contains the parsed value.
|
||||
|
||||
@tparam BasicJsonType the JSON type
|
||||
*/
|
||||
|
||||
template<typename BasicJsonType>
|
||||
class json_sax_dom_parser
|
||||
class json_sax_exception_handler : public json_sax<BasicJsonType>
|
||||
{
|
||||
protected:
|
||||
/// whether a syntax error occurred
|
||||
bool errored = false;
|
||||
/// whether to throw exceptions in case of errors
|
||||
const bool allow_exceptions = true;
|
||||
|
||||
public:
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
|
||||
explicit json_sax_exception_handler(const bool allow_exceptions_)
|
||||
: errored{false}, allow_exceptions{allow_exceptions_}
|
||||
{}
|
||||
|
||||
|
||||
template<class Exception>
|
||||
bool handle_throw_exception(const Exception& ex)
|
||||
{
|
||||
errored = true;
|
||||
static_cast<void>(ex);
|
||||
if (allow_exceptions)
|
||||
{
|
||||
JSON_THROW(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& ex) override
|
||||
{
|
||||
return handle_throw_exception(ex);
|
||||
}
|
||||
|
||||
template<class Exception>
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const Exception& ex)
|
||||
{
|
||||
return handle_throw_exception(ex);
|
||||
}
|
||||
|
||||
constexpr bool is_errored() const
|
||||
{
|
||||
return errored;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
class json_sax_dom_parser : public json_sax_exception_handler<BasicJsonType>
|
||||
{
|
||||
public:
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
@ -174,7 +307,7 @@ class json_sax_dom_parser
|
||||
@param[in] allow_exceptions_ whether parse errors yield exceptions
|
||||
*/
|
||||
explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
|
||||
: root(r), allow_exceptions(allow_exceptions_)
|
||||
: root(r), json_sax_exception_handler<BasicJsonType>(allow_exceptions_)
|
||||
{}
|
||||
|
||||
// make class move-only
|
||||
@ -184,49 +317,49 @@ class json_sax_dom_parser
|
||||
json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||
~json_sax_dom_parser() = default;
|
||||
|
||||
bool null()
|
||||
bool null() override
|
||||
{
|
||||
handle_value(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool val)
|
||||
bool boolean(bool val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(number_integer_t val)
|
||||
bool number_integer(number_integer_t val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(number_unsigned_t val)
|
||||
bool number_unsigned(number_unsigned_t val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(number_float_t val, const string_t& /*unused*/)
|
||||
bool number_float(number_float_t val, const string_t& /*unused*/) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(string_t& val)
|
||||
bool string(string_t& val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(binary_t& val)
|
||||
bool binary(binary_t& val) override
|
||||
{
|
||||
handle_value(std::move(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t len)
|
||||
bool start_object(std::size_t len) override
|
||||
{
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
|
||||
|
||||
@ -238,7 +371,7 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key(string_t& val)
|
||||
bool key(string_t& val) override
|
||||
{
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
@ -248,7 +381,7 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
bool end_object() override
|
||||
{
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(ref_stack.back()->is_object());
|
||||
@ -258,7 +391,7 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t len)
|
||||
bool start_array(std::size_t len) override
|
||||
{
|
||||
ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
|
||||
|
||||
@ -270,7 +403,7 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
bool end_array() override
|
||||
{
|
||||
JSON_ASSERT(!ref_stack.empty());
|
||||
JSON_ASSERT(ref_stack.back()->is_array());
|
||||
@ -280,23 +413,6 @@ class json_sax_dom_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Exception>
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||
const Exception& ex)
|
||||
{
|
||||
errored = true;
|
||||
static_cast<void>(ex);
|
||||
if (allow_exceptions)
|
||||
{
|
||||
JSON_THROW(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool is_errored() const
|
||||
{
|
||||
return errored;
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
@ -335,14 +451,11 @@ class json_sax_dom_parser
|
||||
std::vector<BasicJsonType*> ref_stack {};
|
||||
/// helper to hold the reference for the next object element
|
||||
BasicJsonType* object_element = nullptr;
|
||||
/// whether a syntax error occurred
|
||||
bool errored = false;
|
||||
/// whether to throw exceptions in case of errors
|
||||
const bool allow_exceptions = true;
|
||||
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
class json_sax_dom_callback_parser
|
||||
class json_sax_dom_callback_parser : public json_sax_exception_handler<BasicJsonType>
|
||||
{
|
||||
public:
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
@ -356,7 +469,7 @@ class json_sax_dom_callback_parser
|
||||
json_sax_dom_callback_parser(BasicJsonType& r,
|
||||
const parser_callback_t cb,
|
||||
const bool allow_exceptions_ = true)
|
||||
: root(r), callback(cb), allow_exceptions(allow_exceptions_)
|
||||
: root(r), callback(cb), json_sax_exception_handler<BasicJsonType>(allow_exceptions_)
|
||||
{
|
||||
keep_stack.push_back(true);
|
||||
}
|
||||
@ -368,49 +481,49 @@ class json_sax_dom_callback_parser
|
||||
json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
|
||||
~json_sax_dom_callback_parser() = default;
|
||||
|
||||
bool null()
|
||||
bool null() override
|
||||
{
|
||||
handle_value(nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool val)
|
||||
bool boolean(bool val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(number_integer_t val)
|
||||
bool number_integer(number_integer_t val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(number_unsigned_t val)
|
||||
bool number_unsigned(number_unsigned_t val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(number_float_t val, const string_t& /*unused*/)
|
||||
bool number_float(number_float_t val, const string_t& /*unused*/) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(string_t& val)
|
||||
bool string(string_t& val) override
|
||||
{
|
||||
handle_value(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(binary_t& val)
|
||||
bool binary(binary_t& val) override
|
||||
{
|
||||
handle_value(std::move(val));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t len)
|
||||
bool start_object(std::size_t len) override
|
||||
{
|
||||
// check callback for object start
|
||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
|
||||
@ -428,7 +541,7 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key(string_t& val)
|
||||
bool key(string_t& val) override
|
||||
{
|
||||
BasicJsonType k = BasicJsonType(val);
|
||||
|
||||
@ -445,7 +558,7 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
bool end_object() override
|
||||
{
|
||||
if (ref_stack.back())
|
||||
{
|
||||
@ -481,7 +594,7 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t len)
|
||||
bool start_array(std::size_t len) override
|
||||
{
|
||||
const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
|
||||
keep_stack.push_back(keep);
|
||||
@ -498,7 +611,7 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
bool end_array() override
|
||||
{
|
||||
bool keep = true;
|
||||
|
||||
@ -530,23 +643,6 @@ class json_sax_dom_callback_parser
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Exception>
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
|
||||
const Exception& ex)
|
||||
{
|
||||
errored = true;
|
||||
static_cast<void>(ex);
|
||||
if (allow_exceptions)
|
||||
{
|
||||
JSON_THROW(ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr bool is_errored() const
|
||||
{
|
||||
return errored;
|
||||
}
|
||||
|
||||
private:
|
||||
/*!
|
||||
@ -638,18 +734,14 @@ class json_sax_dom_callback_parser
|
||||
std::vector<bool> key_keep_stack {};
|
||||
/// helper to hold the reference for the next object element
|
||||
BasicJsonType* object_element = nullptr;
|
||||
/// whether a syntax error occurred
|
||||
bool errored = false;
|
||||
/// callback function
|
||||
const parser_callback_t callback = nullptr;
|
||||
/// whether to throw exceptions in case of errors
|
||||
const bool allow_exceptions = true;
|
||||
/// a discarded value for the callback
|
||||
BasicJsonType discarded = BasicJsonType::value_t::discarded;
|
||||
};
|
||||
|
||||
template<typename BasicJsonType>
|
||||
class json_sax_acceptor
|
||||
class json_sax_acceptor : public msgpack_sax<BasicJsonType>
|
||||
{
|
||||
public:
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
@ -658,67 +750,117 @@ class json_sax_acceptor
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
|
||||
bool null()
|
||||
bool null() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool /*unused*/)
|
||||
bool boolean(bool /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(number_integer_t /*unused*/)
|
||||
bool number_integer(number_integer_t /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(number_unsigned_t /*unused*/)
|
||||
bool number_unsigned(number_unsigned_t /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
|
||||
bool number_float(number_float_t /*unused*/, const string_t& /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(string_t& /*unused*/)
|
||||
bool string(string_t& /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(binary_t& /*unused*/)
|
||||
bool binary(binary_t& /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
|
||||
bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key(string_t& /*unused*/)
|
||||
bool end_array() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1)) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
|
||||
bool end_object() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
bool key(string_t& /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
|
||||
bool key_null() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_boolean(bool /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_integer(number_integer_t /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_unsigned(number_unsigned_t /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_float(number_float_t /*unused*/, const string_t& /*unused*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_binary(binary_t& /*val*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_key_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_key_array() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_key_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_key_object() override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <cstdint> // size_t
|
||||
#include <utility> // declval
|
||||
#include <string> // string
|
||||
#include <type_traits>
|
||||
|
||||
#include <nlohmann/detail/abi_macros.hpp>
|
||||
#include <nlohmann/detail/meta/detected.hpp>
|
||||
@ -23,84 +24,150 @@ namespace detail
|
||||
template<typename T>
|
||||
using null_function_t = decltype(std::declval<T&>().null());
|
||||
|
||||
template<typename T>
|
||||
using key_null_function_t = decltype(std::declval<T&>().key_null());
|
||||
|
||||
|
||||
template<typename T>
|
||||
using boolean_function_t =
|
||||
decltype(std::declval<T&>().boolean(std::declval<bool>()));
|
||||
|
||||
template<typename T>
|
||||
using key_boolean_function_t =
|
||||
decltype(std::declval<T&>().key_boolean(std::declval<bool>()));
|
||||
|
||||
|
||||
template<typename T, typename Integer>
|
||||
using number_integer_function_t =
|
||||
decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
|
||||
|
||||
template<typename T, typename Integer>
|
||||
using key_number_integer_function_t =
|
||||
decltype(std::declval<T&>().key_number_integer(std::declval<Integer>()));
|
||||
|
||||
|
||||
template<typename T, typename Unsigned>
|
||||
using number_unsigned_function_t =
|
||||
decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
|
||||
|
||||
template<typename T, typename Unsigned>
|
||||
using key_number_unsigned_function_t =
|
||||
decltype(std::declval<T&>().key_number_unsigned(std::declval<Unsigned>()));
|
||||
|
||||
|
||||
template<typename T, typename Float, typename String>
|
||||
using number_float_function_t = decltype(std::declval<T&>().number_float(
|
||||
std::declval<Float>(), std::declval<const String&>()));
|
||||
|
||||
template<typename T, typename Float, typename String>
|
||||
using key_number_float_function_t = decltype(std::declval<T&>().key_number_float(
|
||||
std::declval<Float>(), std::declval<const String&>()));
|
||||
|
||||
|
||||
template<typename T, typename String>
|
||||
using string_function_t =
|
||||
decltype(std::declval<T&>().string(std::declval<String&>()));
|
||||
|
||||
template<typename T, typename Binary>
|
||||
using binary_function_t =
|
||||
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
||||
|
||||
template<typename T>
|
||||
using start_object_function_t =
|
||||
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
||||
|
||||
template<typename T, typename String>
|
||||
using key_function_t =
|
||||
decltype(std::declval<T&>().key(std::declval<String&>()));
|
||||
|
||||
template<typename T>
|
||||
using end_object_function_t = decltype(std::declval<T&>().end_object());
|
||||
|
||||
template<typename T, typename Binary>
|
||||
using binary_function_t =
|
||||
decltype(std::declval<T&>().binary(std::declval<Binary&>()));
|
||||
|
||||
template<typename T, typename Binary>
|
||||
using key_binary_function_t =
|
||||
decltype(std::declval<T&>().key_binary(std::declval<Binary&>()));
|
||||
|
||||
|
||||
template<typename T>
|
||||
using start_array_function_t =
|
||||
decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
|
||||
|
||||
template<typename T>
|
||||
using start_key_array_function_t =
|
||||
decltype(std::declval<T&>().start_key_array(std::declval<std::size_t>()));
|
||||
|
||||
|
||||
template<typename T>
|
||||
using end_array_function_t = decltype(std::declval<T&>().end_array());
|
||||
|
||||
template<typename T>
|
||||
using end_key_array_function_t = decltype(std::declval<T&>().end_key_array());
|
||||
|
||||
|
||||
template<typename T>
|
||||
using start_object_function_t =
|
||||
decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
|
||||
|
||||
template<typename T>
|
||||
using start_key_object_function_t =
|
||||
decltype(std::declval<T&>().start_key_object(std::declval<std::size_t>()));
|
||||
|
||||
|
||||
template<typename T>
|
||||
using end_object_function_t = decltype(std::declval<T&>().end_object());
|
||||
|
||||
template<typename T>
|
||||
using end_key_object_function_t = decltype(std::declval<T&>().end_key_object());
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T, typename Exception>
|
||||
using parse_error_function_t = decltype(std::declval<T&>().parse_error(
|
||||
std::declval<std::size_t>(), std::declval<const std::string&>(),
|
||||
std::declval<const Exception&>()));
|
||||
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
struct is_sax
|
||||
template<typename SAX, typename BasicJsonType, typename IsTrue = conjunction<
|
||||
is_detected_exact<bool, null_function_t, SAX>,
|
||||
is_detected_exact<bool, boolean_function_t, SAX>,
|
||||
is_detected_exact<bool, number_integer_function_t, SAX, typename BasicJsonType::number_integer_t>,
|
||||
is_detected_exact<bool, number_unsigned_function_t, SAX, typename BasicJsonType::number_unsigned_t>,
|
||||
is_detected_exact<bool, number_float_function_t, SAX, typename BasicJsonType::number_float_t, typename BasicJsonType::string_t>,
|
||||
is_detected_exact<bool, string_function_t, SAX, typename BasicJsonType::string_t>,
|
||||
is_detected_exact<bool, binary_function_t, SAX, typename BasicJsonType::binary_t>,
|
||||
is_detected_exact<bool, key_function_t, SAX, typename BasicJsonType::string_t>,
|
||||
is_detected_exact<bool, start_array_function_t, SAX>,
|
||||
is_detected_exact<bool, end_array_function_t, SAX>,
|
||||
is_detected_exact<bool, start_object_function_t, SAX>,
|
||||
is_detected_exact<bool, end_object_function_t, SAX>,
|
||||
is_detected_exact<bool, parse_error_function_t, SAX, typename BasicJsonType::exception>
|
||||
>
|
||||
>
|
||||
struct is_sax : IsTrue
|
||||
{
|
||||
private:
|
||||
static_assert(is_basic_json<BasicJsonType>::value,
|
||||
"BasicJsonType must be of type basic_json<...>");
|
||||
|
||||
using number_integer_t = typename BasicJsonType::number_integer_t;
|
||||
using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
|
||||
using number_float_t = typename BasicJsonType::number_float_t;
|
||||
using string_t = typename BasicJsonType::string_t;
|
||||
using binary_t = typename BasicJsonType::binary_t;
|
||||
using exception_t = typename BasicJsonType::exception;
|
||||
|
||||
public:
|
||||
static constexpr bool value =
|
||||
is_detected_exact<bool, null_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, boolean_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
|
||||
is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
|
||||
is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
|
||||
is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
|
||||
is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
|
||||
is_detected_exact<bool, start_object_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
|
||||
is_detected_exact<bool, end_object_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, start_array_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, end_array_function_t, SAX>::value &&
|
||||
is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
|
||||
};
|
||||
|
||||
|
||||
template<typename SAX, typename BasicJsonType, typename IsTrue = conjunction<
|
||||
is_sax<SAX, BasicJsonType>,
|
||||
is_detected_exact<bool, key_null_function_t, SAX>,
|
||||
is_detected_exact<bool, key_boolean_function_t, SAX>,
|
||||
is_detected_exact<bool, key_number_integer_function_t, SAX, typename BasicJsonType::number_integer_t>,
|
||||
is_detected_exact<bool, key_number_unsigned_function_t, SAX, typename BasicJsonType::number_unsigned_t>,
|
||||
is_detected_exact<bool, key_number_float_function_t, SAX, typename BasicJsonType::number_float_t, typename BasicJsonType::string_t>,
|
||||
is_detected_exact<bool, key_binary_function_t, SAX, typename BasicJsonType::binary_t>,
|
||||
is_detected_exact<bool, start_array_function_t, SAX>,
|
||||
is_detected_exact<bool, end_array_function_t, SAX>,
|
||||
is_detected_exact<bool, start_key_object_function_t, SAX>,
|
||||
is_detected_exact<bool, end_key_object_function_t, SAX>
|
||||
>
|
||||
>
|
||||
struct is_sax_msgpack : IsTrue
|
||||
{
|
||||
private:
|
||||
static_assert(is_basic_json<BasicJsonType>::value,
|
||||
"BasicJsonType must be of type basic_json<...>");
|
||||
};
|
||||
|
||||
|
||||
template<typename SAX, typename BasicJsonType>
|
||||
struct is_sax_static_asserts
|
||||
{
|
||||
|
||||
1
include/test_data.hpp
Normal file
1
include/test_data.hpp
Normal file
@ -0,0 +1 @@
|
||||
#define TEST_DATA_DIRECTORY "/Users/lucapassarella/Documents/projects/json/json_test_data"
|
||||
File diff suppressed because it is too large
Load Diff
344
tests/src/test_sax_helpers.hpp
Normal file
344
tests/src/test_sax_helpers.hpp
Normal file
@ -0,0 +1,344 @@
|
||||
#pragma once
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class SaxEventLogger : public nlohmann::msgpack_sax<nlohmann::json>
|
||||
{
|
||||
public:
|
||||
|
||||
std::vector<std::string> events {};
|
||||
bool errored = false;
|
||||
|
||||
bool null() override
|
||||
{
|
||||
events.emplace_back("null()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool val) override
|
||||
{
|
||||
events.emplace_back(val ? "boolean(true)" : "boolean(false)");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t val) override
|
||||
{
|
||||
events.push_back("number_integer(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t val) override
|
||||
{
|
||||
events.push_back("number_unsigned(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& s) override
|
||||
{
|
||||
events.push_back("number_float(" + s + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(std::string& val) override
|
||||
{
|
||||
events.push_back("string(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(json::binary_t& val) override
|
||||
{
|
||||
std::string binary_contents = "binary(";
|
||||
std::string comma_space;
|
||||
for (auto b : val)
|
||||
{
|
||||
binary_contents.append(comma_space);
|
||||
binary_contents.append(std::to_string(static_cast<int>(b)));
|
||||
comma_space = ", ";
|
||||
}
|
||||
binary_contents.append(")");
|
||||
events.push_back(binary_contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_array()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_array(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array() override
|
||||
{
|
||||
events.emplace_back("end_array()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_object()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_object(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object() override
|
||||
{
|
||||
events.emplace_back("end_object()");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool key(std::string& val) override
|
||||
{
|
||||
events.push_back("key(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool key_null() override
|
||||
{
|
||||
events.push_back("key_null()");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool key_boolean(bool val) override
|
||||
{
|
||||
events.push_back("key_bool(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool key_integer(json::number_integer_t val) override
|
||||
{
|
||||
events.push_back("key_integer(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool key_unsigned(json::number_unsigned_t val) override
|
||||
{
|
||||
events.push_back("key_unsigned(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool key_float(json::number_float_t val, const json::string_t& s) override
|
||||
{
|
||||
events.push_back("key_float(" + s + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key_binary(binary_t& val) override
|
||||
{
|
||||
std::string binary_contents = "key_binary(";
|
||||
std::string comma_space;
|
||||
for (auto b : val)
|
||||
{
|
||||
binary_contents.append(comma_space);
|
||||
binary_contents.append(std::to_string(static_cast<int>(b)));
|
||||
comma_space = ", ";
|
||||
}
|
||||
binary_contents.append(")");
|
||||
events.push_back(binary_contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_key_array(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_key_array()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_key_array(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_key_array() override
|
||||
{
|
||||
events.emplace_back("end_key_array()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_key_object(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_key_object()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_key_object(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_key_object() override
|
||||
{
|
||||
events.emplace_back("end_key_object()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t position, const std::string& /*unused*/, const json::exception& /*unused*/) override
|
||||
{
|
||||
errored = true;
|
||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
class SaxCountdown : public nlohmann::msgpack_sax<nlohmann::json>
|
||||
{
|
||||
|
||||
protected:
|
||||
int events_left = 0;
|
||||
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(json::binary_t& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_null() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_boolean(bool /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_integer(number_integer_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_unsigned(number_unsigned_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_float(number_float_t /*val*/, const string_t& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key_binary(binary_t& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_key_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_key_array() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_key_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_key_object() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
|
||||
{
|
||||
public:
|
||||
explicit sax_no_exception(json& j)
|
||||
: nlohmann::detail::json_sax_dom_parser<json>(j, false)
|
||||
{}
|
||||
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) override
|
||||
{
|
||||
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
return false;
|
||||
}
|
||||
|
||||
static std::string* error_string;
|
||||
};
|
||||
@ -645,83 +645,7 @@ TEST_CASE("BSON input/output_adapters")
|
||||
}
|
||||
}
|
||||
|
||||
namespace
|
||||
{
|
||||
class SaxCountdown
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(std::vector<std::uint8_t>& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
} // namespace
|
||||
#include "test_sax_helpers.hpp"
|
||||
|
||||
TEST_CASE("Incomplete BSON Input")
|
||||
{
|
||||
|
||||
@ -19,84 +19,7 @@ using nlohmann::json;
|
||||
#include <set>
|
||||
#include "make_test_data_available.hpp"
|
||||
#include "test_utils.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class SaxCountdown
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(std::vector<std::uint8_t>& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
} // namespace
|
||||
#include "test_sax_helpers.hpp"
|
||||
|
||||
TEST_CASE("CBOR")
|
||||
{
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
|
||||
#define JSON_TESTS_PRIVATE
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "test_sax_helpers.hpp"
|
||||
using nlohmann::json;
|
||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
@ -19,189 +20,6 @@ using nlohmann::json;
|
||||
|
||||
namespace
|
||||
{
|
||||
class SaxEventLogger
|
||||
{
|
||||
public:
|
||||
bool null()
|
||||
{
|
||||
events.emplace_back("null()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool val)
|
||||
{
|
||||
events.emplace_back(val ? "boolean(true)" : "boolean(false)");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t val)
|
||||
{
|
||||
events.push_back("number_integer(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t val)
|
||||
{
|
||||
events.push_back("number_unsigned(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& s)
|
||||
{
|
||||
events.push_back("number_float(" + s + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(std::string& val)
|
||||
{
|
||||
events.push_back("string(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(json::binary_t& val)
|
||||
{
|
||||
std::string binary_contents = "binary(";
|
||||
std::string comma_space;
|
||||
for (auto b : val)
|
||||
{
|
||||
binary_contents.append(comma_space);
|
||||
binary_contents.append(std::to_string(static_cast<int>(b)));
|
||||
comma_space = ", ";
|
||||
}
|
||||
binary_contents.append(")");
|
||||
events.push_back(binary_contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t elements)
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_object()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_object(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key(std::string& val)
|
||||
{
|
||||
events.push_back("key(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
events.emplace_back("end_object()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t elements)
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_array()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_array(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
events.emplace_back("end_array()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t position, const std::string& /*unused*/, const json::exception& /*unused*/)
|
||||
{
|
||||
errored = true;
|
||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> events {};
|
||||
bool errored = false;
|
||||
};
|
||||
|
||||
class SaxCountdown : public nlohmann::json::json_sax_t
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(json::binary_t& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*val*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*elements*/) override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array() override
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
|
||||
json parser_helper(const std::string& s);
|
||||
bool accept_helper(const std::string& s);
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "doctest_compatibility.h"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include "test_sax_helpers.hpp"
|
||||
using nlohmann::json;
|
||||
#ifdef JSON_TEST_NO_GLOBAL_UDLS
|
||||
using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
|
||||
@ -22,111 +23,6 @@ using nlohmann::json;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct SaxEventLogger : public nlohmann::json_sax<json>
|
||||
{
|
||||
bool null() override
|
||||
{
|
||||
events.emplace_back("null()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool boolean(bool val) override
|
||||
{
|
||||
events.emplace_back(val ? "boolean(true)" : "boolean(false)");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t val) override
|
||||
{
|
||||
events.push_back("number_integer(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t val) override
|
||||
{
|
||||
events.push_back("number_unsigned(" + std::to_string(val) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*val*/, const std::string& s) override
|
||||
{
|
||||
events.push_back("number_float(" + s + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool string(std::string& val) override
|
||||
{
|
||||
events.push_back("string(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool binary(json::binary_t& val) override
|
||||
{
|
||||
std::string binary_contents = "binary(";
|
||||
std::string comma_space;
|
||||
for (auto b : val)
|
||||
{
|
||||
binary_contents.append(comma_space);
|
||||
binary_contents.append(std::to_string(static_cast<int>(b)));
|
||||
comma_space = ", ";
|
||||
}
|
||||
binary_contents.append(")");
|
||||
events.push_back(binary_contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_object()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_object(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool key(std::string& val) override
|
||||
{
|
||||
events.push_back("key(" + val + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_object() override
|
||||
{
|
||||
events.emplace_back("end_object()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t elements) override
|
||||
{
|
||||
if (elements == static_cast<std::size_t>(-1))
|
||||
{
|
||||
events.emplace_back("start_array()");
|
||||
}
|
||||
else
|
||||
{
|
||||
events.push_back("start_array(" + std::to_string(elements) + ")");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool end_array() override
|
||||
{
|
||||
events.emplace_back("end_array()");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t position, const std::string& /*last_token*/, const json::exception& /*ex*/) override
|
||||
{
|
||||
events.push_back("parse_error(" + std::to_string(position) + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> events {};
|
||||
};
|
||||
|
||||
struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger
|
||||
{
|
||||
|
||||
@ -25,7 +25,7 @@ class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
|
||||
public:
|
||||
explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser<json>(j, false) {}
|
||||
|
||||
static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) override
|
||||
{
|
||||
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
return false;
|
||||
|
||||
@ -21,84 +21,7 @@ using nlohmann::json;
|
||||
#include <set>
|
||||
#include "make_test_data_available.hpp"
|
||||
#include "test_utils.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class SaxCountdown
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(std::vector<std::uint8_t>& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
} // namespace
|
||||
#include "test_sax_helpers.hpp"
|
||||
|
||||
TEST_CASE("MessagePack")
|
||||
{
|
||||
@ -1445,7 +1368,7 @@ TEST_CASE("MessagePack")
|
||||
json _;
|
||||
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x87})),
|
||||
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack string: unexpected end of input", json::parse_error&);
|
||||
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack key: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcc})),
|
||||
"[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing MessagePack number: unexpected end of input", json::parse_error&);
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0xcd})),
|
||||
@ -1531,12 +1454,14 @@ TEST_CASE("MessagePack")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("invalid string in map")
|
||||
{
|
||||
json _;
|
||||
CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF", json::parse_error&);
|
||||
CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
|
||||
}
|
||||
// THIS TEST SHOULD FAIL NO MORE!
|
||||
// INT AS KEY IN MSGPACK IS NOW SUPPORTED!
|
||||
// SECTION("invalid string in map")
|
||||
// {
|
||||
// json _;
|
||||
// CHECK_THROWS_WITH_AS(_ = json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01})), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing MessagePack string: expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0xFF", json::parse_error&);
|
||||
// CHECK(json::from_msgpack(std::vector<uint8_t>({0x81, 0xff, 0x01}), true, false).is_discarded());
|
||||
// }
|
||||
|
||||
SECTION("strict mode")
|
||||
{
|
||||
|
||||
@ -165,13 +165,11 @@ struct adl_serializer<NonDefaultConstructible>
|
||||
class sax_no_exception : public nlohmann::detail::json_sax_dom_parser<json>
|
||||
{
|
||||
public:
|
||||
explicit sax_no_exception(json& j)
|
||||
: nlohmann::detail::json_sax_dom_parser<json>(j, false)
|
||||
{}
|
||||
explicit sax_no_exception(json& j) : nlohmann::detail::json_sax_dom_parser<json>(j, false) {}
|
||||
|
||||
static bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex)
|
||||
bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& ex) override
|
||||
{
|
||||
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
error_string = new std::string(ex.what()); // NOLINT(cppcoreguidelines-owning-memory)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -16,84 +16,7 @@ using nlohmann::json;
|
||||
#include <set>
|
||||
#include "make_test_data_available.hpp"
|
||||
#include "test_utils.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
class SaxCountdown
|
||||
{
|
||||
public:
|
||||
explicit SaxCountdown(const int count) : events_left(count)
|
||||
{}
|
||||
|
||||
bool null()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool boolean(bool /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_integer(json::number_integer_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_unsigned(json::number_unsigned_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool string(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool binary(std::vector<std::uint8_t>& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_object(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool key(std::string& /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_object()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool start_array(std::size_t /*unused*/)
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool end_array()
|
||||
{
|
||||
return events_left-- > 0;
|
||||
}
|
||||
|
||||
bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
int events_left = 0;
|
||||
};
|
||||
} // namespace
|
||||
#include "test_sax_helpers.hpp"
|
||||
|
||||
TEST_CASE("UBJSON")
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user