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