🐛 fix bug in SAX callback parser
This commit is contained in:
parent
cf4a6552f3
commit
f0c6ab4d3b
5 changed files with 58 additions and 66 deletions
|
@ -214,7 +214,7 @@ class json_sax_dom_parser
|
||||||
|
|
||||||
bool binary(binary_t& val)
|
bool binary(binary_t& val)
|
||||||
{
|
{
|
||||||
handle_binary(val);
|
handle_value(BasicJsonType::binary_array(std::move(val)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,36 +327,6 @@ class json_sax_dom_parser
|
||||||
return object_element;
|
return object_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@invariant If the ref stack is empty, then the passed value will be the new
|
|
||||||
root.
|
|
||||||
@invariant If the ref stack contains a value, then it is an array or an
|
|
||||||
object to which we can add elements
|
|
||||||
*/
|
|
||||||
template<typename BinaryValue>
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
BasicJsonType* handle_binary(BinaryValue&& v)
|
|
||||||
{
|
|
||||||
if (ref_stack.empty())
|
|
||||||
{
|
|
||||||
root = BasicJsonType::binary_array(std::forward<BinaryValue>(v));
|
|
||||||
return &root;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
|
||||||
|
|
||||||
if (ref_stack.back()->is_array())
|
|
||||||
{
|
|
||||||
ref_stack.back()->m_value.array->emplace_back(BasicJsonType::binary_array(std::forward<BinaryValue>(v)));
|
|
||||||
return &(ref_stack.back()->m_value.array->back());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(ref_stack.back()->is_object());
|
|
||||||
assert(object_element);
|
|
||||||
*object_element = BasicJsonType::binary_array(std::forward<BinaryValue>(v));
|
|
||||||
return object_element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// stack to model hierarchy of values
|
||||||
|
@ -434,7 +404,7 @@ class json_sax_dom_callback_parser
|
||||||
|
|
||||||
bool binary(binary_t& val)
|
bool binary(binary_t& val)
|
||||||
{
|
{
|
||||||
handle_value(val);
|
handle_value(BasicJsonType::binary_array(val));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2794,7 +2794,7 @@ class basic_json
|
||||||
/// get a pointer to the value (binary)
|
/// get a pointer to the value (binary)
|
||||||
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
|
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
|
||||||
{
|
{
|
||||||
return is_binary() ? m_value.binary : nullptr;
|
return is_binary() ? reinterpret_cast<binary_t*>(m_value.binary) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a pointer to the value (binary)
|
/// get a pointer to the value (binary)
|
||||||
|
|
|
@ -4881,7 +4881,7 @@ class json_sax_dom_parser
|
||||||
|
|
||||||
bool binary(binary_t& val)
|
bool binary(binary_t& val)
|
||||||
{
|
{
|
||||||
handle_binary(val);
|
handle_value(BasicJsonType::binary_array(std::move(val)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4994,36 +4994,6 @@ class json_sax_dom_parser
|
||||||
return object_element;
|
return object_element;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
|
||||||
@invariant If the ref stack is empty, then the passed value will be the new
|
|
||||||
root.
|
|
||||||
@invariant If the ref stack contains a value, then it is an array or an
|
|
||||||
object to which we can add elements
|
|
||||||
*/
|
|
||||||
template<typename BinaryValue>
|
|
||||||
JSON_HEDLEY_RETURNS_NON_NULL
|
|
||||||
BasicJsonType* handle_binary(BinaryValue&& v)
|
|
||||||
{
|
|
||||||
if (ref_stack.empty())
|
|
||||||
{
|
|
||||||
root = BasicJsonType::binary_array(std::forward<BinaryValue>(v));
|
|
||||||
return &root;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(ref_stack.back()->is_array() or ref_stack.back()->is_object());
|
|
||||||
|
|
||||||
if (ref_stack.back()->is_array())
|
|
||||||
{
|
|
||||||
ref_stack.back()->m_value.array->emplace_back(BasicJsonType::binary_array(std::forward<BinaryValue>(v)));
|
|
||||||
return &(ref_stack.back()->m_value.array->back());
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(ref_stack.back()->is_object());
|
|
||||||
assert(object_element);
|
|
||||||
*object_element = BasicJsonType::binary_array(std::forward<BinaryValue>(v));
|
|
||||||
return object_element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// the parsed JSON value
|
/// the parsed JSON value
|
||||||
BasicJsonType& root;
|
BasicJsonType& root;
|
||||||
/// stack to model hierarchy of values
|
/// stack to model hierarchy of values
|
||||||
|
@ -5101,7 +5071,7 @@ class json_sax_dom_callback_parser
|
||||||
|
|
||||||
bool binary(binary_t& val)
|
bool binary(binary_t& val)
|
||||||
{
|
{
|
||||||
handle_value(val);
|
handle_value(BasicJsonType::binary_array(val));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18280,7 +18250,7 @@ class basic_json
|
||||||
/// get a pointer to the value (binary)
|
/// get a pointer to the value (binary)
|
||||||
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
|
binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
|
||||||
{
|
{
|
||||||
return is_binary() ? m_value.binary : nullptr;
|
return is_binary() ? reinterpret_cast<binary_t*>(m_value.binary) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// get a pointer to the value (binary)
|
/// get a pointer to the value (binary)
|
||||||
|
|
|
@ -1442,6 +1442,29 @@ TEST_CASE("CBOR")
|
||||||
std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x40};
|
std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x40};
|
||||||
CHECK_NOTHROW(json::from_cbor(input));
|
CHECK_NOTHROW(json::from_cbor(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("SAX callback with binary")
|
||||||
|
{
|
||||||
|
// object mapping "foo" to byte string
|
||||||
|
std::vector<std::uint8_t> input = {0xA1, 0x63, 0x66, 0x6F, 0x6F, 0x41, 0x00};
|
||||||
|
|
||||||
|
// callback to set binary_seen to true if a binary value was seen
|
||||||
|
bool binary_seen = false;
|
||||||
|
auto callback = [&binary_seen](int /*depth*/, json::parse_event_t /*event*/, json & parsed)
|
||||||
|
{
|
||||||
|
if (parsed.is_binary())
|
||||||
|
{
|
||||||
|
binary_seen = true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
json j;
|
||||||
|
auto cbp = nlohmann::detail::json_sax_dom_callback_parser<json>(j, callback, true);
|
||||||
|
CHECK(json::sax_parse(input, &cbp, json::input_format_t::cbor));
|
||||||
|
CHECK(j.at("foo").is_binary());
|
||||||
|
CHECK(binary_seen);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -442,4 +442,33 @@ TEST_CASE("pointer access")
|
||||||
CHECK(value.get_ptr<const json::number_float_t*>() != nullptr);
|
CHECK(value.get_ptr<const json::number_float_t*>() != nullptr);
|
||||||
CHECK(value.get_ptr<const json::binary_t*>() == nullptr);
|
CHECK(value.get_ptr<const json::binary_t*>() == nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("pointer access to const binary_t")
|
||||||
|
{
|
||||||
|
using test_type = const json::binary_t;
|
||||||
|
const json value = json::binary_array({});
|
||||||
|
|
||||||
|
// check if pointers are returned correctly
|
||||||
|
test_type* p1 = value.get_ptr<test_type*>();
|
||||||
|
CHECK(p1 == value.get_ptr<test_type*>());
|
||||||
|
//CHECK(*p1 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* p2 = value.get_ptr<const test_type*>();
|
||||||
|
CHECK(p2 == value.get_ptr<const test_type*>());
|
||||||
|
//CHECK(*p2 == value.get<test_type>());
|
||||||
|
|
||||||
|
const test_type* const p3 = value.get_ptr<const test_type* const>();
|
||||||
|
CHECK(p3 == value.get_ptr<const test_type* const>());
|
||||||
|
//CHECK(*p3 == value.get<test_type>());
|
||||||
|
|
||||||
|
// check if null pointers are returned correctly
|
||||||
|
CHECK(value.get_ptr<const json::object_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::array_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::string_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::boolean_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::number_integer_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::number_unsigned_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::number_float_t*>() == nullptr);
|
||||||
|
CHECK(value.get_ptr<const json::binary_t*>() != nullptr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue