Cache string value locally

This commit is contained in:
John Keiser 2020-08-07 12:45:04 -07:00
parent abd1399a7f
commit 57eb55446f
1 changed files with 52 additions and 40 deletions

View File

@ -10,7 +10,6 @@ public:
uint32_t *next_structural;
dom_parser_implementation &dom_parser;
uint32_t depth{0};
const uint8_t *value{}; // Used to keep a value around between states
template<bool STREAMING, typename T>
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code walk_document(T &visitor) noexcept;
@ -26,9 +25,8 @@ public:
simdjson_really_inline char peek_next_char() {
return buf[*(next_structural)];
}
simdjson_really_inline char advance() {
value = &buf[*(next_structural++)];
return *value;
simdjson_really_inline const uint8_t *advance() {
return &buf[*(next_structural++)];
}
simdjson_really_inline size_t remaining_len() {
return dom_parser.len - *(next_structural-1);
@ -97,29 +95,31 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code json_iterator::walk_docum
//
// Read first value
//
advance();
{
auto value = advance();
// Make sure the outer hash or array is closed before continuing; otherwise, there are ways we
// could get into memory corruption. See https://github.com/simdjson/simdjson/issues/906
if (!STREAMING) {
switch (*value) {
case '{':
if (last_structural() != '}') {
return TAPE_ERROR;
}
break;
case '[':
if (last_structural() != ']') {
return TAPE_ERROR;
}
break;
// Make sure the outer hash or array is closed before continuing; otherwise, there are ways we
// could get into memory corruption. See https://github.com/simdjson/simdjson/issues/906
if (!STREAMING) {
switch (*value) {
case '{':
if (last_structural() != '}') {
return TAPE_ERROR;
}
break;
case '[':
if (last_structural() != ']') {
return TAPE_ERROR;
}
break;
}
}
}
switch (*value) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.root_primitive(*this, value) ); break;
switch (*value) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.root_primitive(*this, value) ); break;
}
}
goto document_end;
@ -131,24 +131,33 @@ object_begin:
if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
SIMDJSON_TRY( visitor.start_object(*this) );
if (advance() != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
visitor.increment_count(*this);
SIMDJSON_TRY( visitor.key(*this, value) );
{
auto key = advance();
if (*key != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
visitor.increment_count(*this);
SIMDJSON_TRY( visitor.key(*this, key) );
}
object_field:
if (simdjson_unlikely( advance() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
switch (advance()) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
if (simdjson_unlikely( *advance() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
{
auto value = advance();
switch (*value) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
}
}
object_continue:
switch (advance()) {
switch (*advance()) {
case ',':
visitor.increment_count(*this);
if (simdjson_unlikely( advance() != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
SIMDJSON_TRY( visitor.key(*this, value) );
{
auto key = advance();
if (simdjson_unlikely( *key != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
SIMDJSON_TRY( visitor.key(*this, key) );
}
goto object_field;
case '}': SIMDJSON_TRY( visitor.end_object(*this) ); goto scope_end;
default: log_error("No comma between object fields"); return TAPE_ERROR;
@ -170,14 +179,17 @@ array_begin:
visitor.increment_count(*this);
array_value:
switch (advance()) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
{
auto value = advance();
switch (*value) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
}
}
array_continue:
switch (advance()) {
switch (*advance()) {
case ',': visitor.increment_count(*this); goto array_value;
case ']': SIMDJSON_TRY( visitor.end_array(*this) ); goto scope_end;
default: log_error("Missing comma between array values"); return TAPE_ERROR;