Move value into common place to be shared across states

This commit is contained in:
John Keiser 2020-08-06 16:46:11 -07:00
parent ce8b9ee8c4
commit 5a3c3134ec
1 changed files with 42 additions and 62 deletions

View File

@ -68,6 +68,8 @@ struct structural_parser : structural_iterator {
template<bool STREAMING, typename T>
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code structural_parser::walk_document(T &visitor) noexcept {
const uint8_t *value;
logger::log_start();
//
@ -79,69 +81,61 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code structural_parser::walk_d
//
// Read first value
//
{
const uint8_t *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;
}
}
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 (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.parse_root_primitive(*this, value) );
case '{':
if (last_structural() != '}') {
return TAPE_ERROR;
}
break;
case '[':
if (last_structural() != ']') {
return TAPE_ERROR;
}
break;
}
goto document_end;
}
switch (*value) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.parse_root_primitive(*this, value) );
}
goto document_end;
//
// Object parser states
//
object_begin: {
object_begin:
depth++;
if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
visitor.start_object(*this);
const uint8_t *key = advance();
if (*key != '"') {
log_error("Object does not start with a key");
return TAPE_ERROR;
}
value = advance();
if (*value != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
visitor.increment_count(*this);
SIMDJSON_TRY( visitor.parse_key(*this, key) );
SIMDJSON_TRY( visitor.parse_key(*this, value) );
goto object_field;
} // object_begin:
object_field: {
object_field:
if (simdjson_unlikely( advance_char() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
const uint8_t *value = advance();
switch (*value) {
switch (*(value = advance())) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.parse_primitive(*this, value) );
}
} // object_field:
object_continue: {
object_continue:
switch (advance_char()) {
case ',': {
visitor.increment_count(*this);
const uint8_t *key = advance();
if (simdjson_unlikely( *key != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
SIMDJSON_TRY( visitor.parse_key(*this, key) );
value = advance();
if (simdjson_unlikely( *value != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
SIMDJSON_TRY( visitor.parse_key(*this, value) );
goto object_field;
}
case '}':
@ -151,50 +145,37 @@ object_continue: {
log_error("No comma between object fields");
return TAPE_ERROR;
}
} // object_continue:
scope_end: {
scope_end:
depth--;
if (depth == 0) { goto document_end; }
if (dom_parser.is_array[depth]) { goto array_continue; }
goto object_continue;
} // scope_end:
//
// Array parser states
//
array_begin: {
array_begin:
depth++;
if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
visitor.start_array(*this);
visitor.increment_count(*this);
} // array_begin:
array_value: {
const uint8_t *value = advance();
switch (*value) {
array_value:
switch (*(value = advance())) {
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
default: SIMDJSON_TRY( visitor.parse_primitive(*this, value) );
}
} // array_value:
array_continue: {
array_continue:
switch (advance_char()) {
case ',':
visitor.increment_count(*this);
goto array_value;
case ']':
visitor.end_array(*this);
goto scope_end;
default:
log_error("Missing comma between array values");
return TAPE_ERROR;
case ',': visitor.increment_count(*this); goto array_value;
case ']': visitor.end_array(*this); goto scope_end;
default: log_error("Missing comma between array values"); return TAPE_ERROR;
}
} // array_continue:
document_end: {
document_end:
visitor.end_document(*this);
dom_parser.next_structural_index = uint32_t(next_structural - &dom_parser.structural_indexes[0]);
@ -211,7 +192,6 @@ document_end: {
}
return SUCCESS;
} // document_end:
} // parse_structurals()