Verifies and fixes issue 1588 (#1589)

* Verifies and fix issue 1588

* Removing a trailing space.
This commit is contained in:
Daniel Lemire 2021-05-27 19:35:42 -04:00 committed by GitHub
parent 16e2323153
commit 1032f70ddf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 161 additions and 2 deletions

View File

@ -129,6 +129,15 @@ simdjson_really_inline bool json_iterator::at_eof() const noexcept {
return token.index == &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes];
}
inline std::string json_iterator::to_string() const noexcept {
if( !is_alive() ) { return "dead json_iterator instance"; }
const char * current_structural = reinterpret_cast<const char *>(token.peek());
return std::string("json_iterator [ depth : ") + std::to_string(_depth)
+ std::string(", structural : '") + std::string(current_structural,1)
+ std::string("', offset : ") + std::to_string(token.current_offset())
+ std::string(" ]");
}
simdjson_really_inline bool json_iterator::is_alive() const noexcept {
return parser;
}

View File

@ -49,7 +49,7 @@ public:
simdjson_really_inline json_iterator() noexcept = default;
simdjson_really_inline json_iterator(json_iterator &&other) noexcept;
simdjson_really_inline json_iterator &operator=(json_iterator &&other) noexcept;
simdjson_really_inline json_iterator(const json_iterator &other) noexcept = delete;
simdjson_really_inline explicit json_iterator(const json_iterator &other) noexcept = default;
simdjson_really_inline json_iterator &operator=(const json_iterator &other) noexcept = delete;
/**
@ -194,6 +194,8 @@ public:
simdjson_really_inline token_position start_position(depth_t depth) const noexcept;
simdjson_really_inline void set_start_position(depth_t depth, token_position position) noexcept;
#endif
/* Useful for debugging and logging purposes. */
inline std::string to_string() const noexcept;
protected:
simdjson_really_inline json_iterator(const uint8_t *buf, ondemand::parser *parser) noexcept;

View File

@ -7,6 +7,11 @@ simdjson_really_inline token_iterator::token_iterator(const uint8_t *_buf, token
{
}
simdjson_really_inline uint32_t token_iterator::current_offset() const noexcept {
return *(index);
}
simdjson_really_inline const uint8_t *token_iterator::advance() noexcept {
return &buf[*(index++)];
}

View File

@ -27,7 +27,10 @@ public:
* Does not check or update depth/expect_value. Caller is responsible for that.
*/
simdjson_really_inline const uint8_t *advance() noexcept;
/**
* Reports the current offset in bytes from the start of the underlying buffer.
*/
simdjson_really_inline uint32_t current_offset() const noexcept;
/**
* Get the JSON text for a given token (relative).
*

View File

@ -216,6 +216,7 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
// at the ':' and we need to move forward through the value... If the value was
// processed then skip_child() does not move the iterator (but may adjust the depth).
if ((error = skip_child() )) { abandon(); return error; }
search_start = _json_iter->position();
// The has_next_field() advances the pointer and check that either ',' or '}' is found.
// It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found,
// then we are in error and we abort.
@ -368,6 +369,13 @@ simdjson_warn_unused simdjson_really_inline simdjson_result<bool> value_iterator
return result;
}
inline std::string value_iterator::to_string() const noexcept {
auto answer = std::string("value_iterator [ depth : ") + std::to_string(_depth) + std::string(", ");
if(_json_iter != nullptr) { answer += _json_iter->to_string(); }
answer += std::string(" ]");
return answer;
}
simdjson_warn_unused simdjson_really_inline bool value_iterator::started_array() noexcept {
assert_at_container_start();
if (*_json_iter->peek() == ']') {

View File

@ -284,6 +284,8 @@ public:
/** @} */
protected:
/* Useful for debugging and logging purposes. */
inline std::string to_string() const noexcept;
simdjson_really_inline value_iterator(json_iterator *json_iter, depth_t depth, token_position start_index) noexcept;
simdjson_really_inline bool parse_null(const uint8_t *json) const noexcept;

View File

@ -6,6 +6,135 @@ using namespace simdjson;
namespace array_tests {
using namespace std;
using simdjson::ondemand::json_type;
bool issue1588() {
TEST_START();
const auto json = R"({
"nodes" : [
{
"rotation" : [
0.16907575726509094,
0.7558803558349609,
-0.27217137813568115,
0.570947527885437
],
"translation" : [
4.076245307922363,
5.903861999511719,
-1.0054539442062378
]
},
{
"camera" : 0,
"rotation" : [
-0.7071067690849304,
0,
0,
0.7071067690849304
]
},
{
"children" : [
1
],
"translation" : [
7.358891487121582,
4.958309173583984,
6.925790786743164
]
},
{
"mesh" : 1,
"scale" : [
4.7498908042907715,
4.7498908042907715,
4.7498908042907715
]
}
]
})"_padded;
// we query 'rotation', 'scale', 'translation' in sequence
const bool expected_value[][3] = { {true, false, true},
{true, false, false}, {false, false, true}, {false, true, false} };
SUBTEST("ondemand::issue1588::sequence", test_ondemand_doc(json, [&](auto doc_result) {
ondemand::array array;
ASSERT_SUCCESS( doc_result["nodes"].get(array) );
size_t i=0;
for (auto value : array) {
ondemand::object current_object;
ASSERT_SUCCESS( value.get_object().get(current_object) );
std::cout << "[ondemand::issue1588::sequence] acquired a new object ==========" << std::endl;
simdjson::ondemand::array rotation;
if(expected_value[i][0]) {
ASSERT_SUCCESS( current_object["rotation"].get(rotation) );
std::cout << "[ondemand::issue1588::sequence] found 'rotation' " << std::endl;
} else {
ASSERT_ERROR( current_object["rotation"].get(rotation), NO_SUCH_FIELD );
std::cout << "[ondemand::issue1588::sequence] rotation not found" << std::endl;
}
simdjson::ondemand::array scale;
if(expected_value[i][1]) {
ASSERT_SUCCESS( current_object["scale"].get(scale) );
std::cout << "[ondemand::issue1588::sequence] found 'scale' " << std::endl;
} else {
ASSERT_ERROR( current_object["scale"].get(scale), NO_SUCH_FIELD );
std::cout << "[ondemand::issue1588::sequence] scale not found" << std::endl;
}
simdjson::ondemand::array translation;
if(expected_value[i][2]) {
ASSERT_SUCCESS( current_object["translation"].get(translation) );
std::cout << "[ondemand::issue1588::sequence] found 'translation' " << std::endl;
} else {
ASSERT_ERROR( current_object["translation"].get(translation), NO_SUCH_FIELD );
std::cout << "[ondemand::issue1588::sequence] translation not found" << std::endl;
}
i++;
}
ASSERT_EQUAL(i, 4);
return true;
}));
SUBTEST("ondemand::issue1588::originalcode", test_ondemand_doc(json, [&](auto doc_result) {
int count_nodes = 0;
simdjson::ondemand::array doc_nodes;
auto error = doc_result["nodes"].get(doc_nodes);
ASSERT_SUCCESS( error );
for (auto node_iterator : doc_nodes) {
ondemand::object node_obj;
ASSERT_SUCCESS( node_iterator.get_object().get(node_obj) );
simdjson::ondemand::array rotation;
std::cout << "checking rotation" << std::endl;
if(expected_value[count_nodes][0]) {
ASSERT_SUCCESS( node_obj["rotation"].get(rotation) );
} else {
ASSERT_ERROR( node_obj["rotation"].get(rotation), NO_SUCH_FIELD );
}
simdjson::ondemand::array scale;
std::cout << "checking scale" << std::endl;
if(expected_value[count_nodes][1]) {
ASSERT_SUCCESS( node_obj["scale"].get(scale) );
} else {
ASSERT_ERROR( node_obj["scale"].get(scale), NO_SUCH_FIELD );
}
simdjson::ondemand::array translation;
std::cout << "checking translation" << std::endl;
if (!error) { std::cout << "translation!\n"; }
if(expected_value[count_nodes][2]) {
ASSERT_SUCCESS( node_obj["translation"].get(translation) );
} else {
ASSERT_ERROR( node_obj["translation"].get(translation), NO_SUCH_FIELD );
}
++count_nodes;
}
ASSERT_EQUAL(count_nodes, 4);
return true;
}));
TEST_SUCCEED();
}
bool iterate_document_array() {
TEST_START();
@ -341,6 +470,7 @@ namespace array_tests {
bool run() {
return
issue1588() &&
iterate_array() &&
iterate_document_array() &&
iterate_empty_array() &&