Merge pull request #1078 from simdjson/jkeiser/no-computed-goto
[2/3] Remove computed GOTOs
This commit is contained in:
commit
86162aaddb
|
@ -56,6 +56,6 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *resu
|
|||
}
|
||||
|
||||
} // namespace arm64
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_ARM64_BITMANIPULATION_H
|
||||
|
|
|
@ -99,7 +99,7 @@ really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, c
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage1/utf8_lookup4_algorithm.h"
|
||||
#include "generic/stage1/json_structural_indexer.h"
|
||||
|
@ -167,6 +167,6 @@ WARN_UNUSED error_code dom_parser_implementation::parse(const uint8_t *_buf, siz
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "arm64/end_implementation.h"
|
||||
|
|
|
@ -17,6 +17,6 @@ WARN_UNUSED error_code implementation::create_dom_parser_implementation(
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "arm64/end_implementation.h"
|
|
@ -23,6 +23,6 @@ public:
|
|||
};
|
||||
|
||||
} // namespace arm64
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_ARM64_IMPLEMENTATION_H
|
||||
|
|
|
@ -15,7 +15,7 @@ static really_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars)
|
|||
}
|
||||
|
||||
} // namespace arm64
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#define SWAR_NUMBER_PARSING
|
||||
|
||||
|
|
|
@ -495,6 +495,6 @@ really_inline int8x16_t make_int8x16_t(int8_t x1, int8_t x2, int8_t x3, int8_
|
|||
|
||||
} // namespace simd
|
||||
} // namespace arm64
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_ARM64_SIMD_H
|
||||
|
|
|
@ -44,7 +44,7 @@ really_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8
|
|||
}
|
||||
|
||||
} // namespace arm64
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage2/stringparsing.h"
|
||||
|
||||
|
|
|
@ -40,6 +40,6 @@ really_inline int leading_zeroes(uint64_t input_num) {
|
|||
}
|
||||
|
||||
} // namespace fallback
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_BITMANIPULATION_H
|
||||
|
|
|
@ -308,7 +308,7 @@ WARN_UNUSED bool implementation::validate_utf8(const char *buf, size_t len) cons
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
//
|
||||
// Stage 2
|
||||
|
@ -344,6 +344,6 @@ WARN_UNUSED error_code dom_parser_implementation::parse(const uint8_t *_buf, siz
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "fallback/end_implementation.h"
|
|
@ -17,6 +17,6 @@ WARN_UNUSED error_code implementation::create_dom_parser_implementation(
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "fallback/end_implementation.h"
|
|
@ -27,6 +27,6 @@ public:
|
|||
};
|
||||
|
||||
} // namespace fallback
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_FALLBACK_IMPLEMENTATION_H
|
|
@ -22,7 +22,7 @@ static really_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars)
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#define SWAR_NUMBER_PARSING
|
||||
#include "generic/stage2/numberparsing.h"
|
||||
|
|
|
@ -27,7 +27,7 @@ really_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8
|
|||
}
|
||||
|
||||
} // namespace fallback
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage2/stringparsing.h"
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ class dom_parser_implementation final : public internal::dom_parser_implementati
|
|||
public:
|
||||
/** Tape location of each open { or [ */
|
||||
std::unique_ptr<scope_descriptor[]> containing_scope{};
|
||||
/** Return address of each open { or [ */
|
||||
std::unique_ptr<ret_address_t[]> ret_address{};
|
||||
/** Whether each open container is a [ or { */
|
||||
std::unique_ptr<bool[]> is_array{};
|
||||
/** Buffer passed to stage 1 */
|
||||
const uint8_t *buf{};
|
||||
/** Length passed to stage 1 */
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
};
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage1/allocate.h"
|
||||
#include "generic/stage2/allocate.h"
|
||||
|
@ -71,4 +71,4 @@ WARN_UNUSED error_code dom_parser_implementation::set_max_depth(size_t max_depth
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -18,4 +18,4 @@ really_inline error_code set_capacity(internal::dom_parser_implementation &parse
|
|||
} // namespace allocate
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -86,4 +86,4 @@ really_inline void buf_block_reader<STEP_SIZE>::advance() {
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -68,4 +68,4 @@ really_inline uint32_t find_next_document_index(dom_parser_implementation &parse
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -78,4 +78,4 @@ error_code json_minifier::minify(const uint8_t *buf, size_t len, uint8_t *dst, s
|
|||
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -92,4 +92,4 @@ really_inline error_code json_scanner::finish(bool streaming) {
|
|||
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -140,4 +140,4 @@ really_inline error_code json_string_scanner::finish(bool streaming) {
|
|||
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -226,4 +226,4 @@ really_inline error_code json_structural_indexer::finish(dom_parser_implementati
|
|||
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -181,4 +181,4 @@ struct utf8_checker {
|
|||
}; // struct utf8_checker
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -217,7 +217,7 @@ using namespace simd;
|
|||
|
||||
}; // struct utf8_checker
|
||||
} // namespace utf8_validation
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
using utf8_validation::utf8_checker;
|
||||
|
||||
|
|
|
@ -237,7 +237,7 @@ using namespace simd;
|
|||
|
||||
}; // struct utf8_checker
|
||||
} // namespace utf8_validation
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
using utf8_validation::utf8_checker;
|
||||
|
||||
|
|
|
@ -178,4 +178,4 @@ using namespace simd;
|
|||
using utf8_validation::utf8_checker;
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -300,4 +300,4 @@ struct utf8_checker {
|
|||
|
||||
} // namespace utf8_validation
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -183,4 +183,4 @@ struct utf8_checker {
|
|||
}; // struct utf8_checker
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -28,4 +28,4 @@ bool generic_validate_utf8(const char * input, size_t length) {
|
|||
|
||||
} // namespace stage1
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -362,4 +362,4 @@ struct utf8_checker {
|
|||
}; // struct utf8_checker
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -8,9 +8,9 @@ namespace allocate {
|
|||
//
|
||||
really_inline error_code set_max_depth(dom_parser_implementation &parser, size_t max_depth) {
|
||||
parser.containing_scope.reset(new (std::nothrow) scope_descriptor[max_depth]);
|
||||
parser.ret_address.reset(new (std::nothrow) ret_address_t[max_depth]);
|
||||
parser.is_array.reset(new (std::nothrow) bool[max_depth]);
|
||||
|
||||
if (!parser.ret_address || !parser.containing_scope) {
|
||||
if (!parser.is_array || !parser.containing_scope) {
|
||||
return MEMALLOC;
|
||||
}
|
||||
return SUCCESS;
|
||||
|
@ -19,4 +19,4 @@ really_inline error_code set_max_depth(dom_parser_implementation &parser, size_t
|
|||
} // namespace allocate
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -61,4 +61,4 @@ really_inline bool is_valid_null_atom(const uint8_t *src, size_t len) {
|
|||
} // namespace atomparsing
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -106,4 +106,4 @@ really_inline value128 full_multiplication(uint64_t value1, uint64_t value2) {
|
|||
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -66,4 +66,4 @@ namespace logger {
|
|||
|
||||
} // namespace logger
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -505,4 +505,4 @@ really_inline bool parse_number(const uint8_t *const src, W &writer) {
|
|||
} // namespace numberparsing
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -122,4 +122,4 @@ WARN_UNUSED really_inline uint8_t *parse_string(const uint8_t *src, uint8_t *dst
|
|||
} // namespace stringparsing
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -47,4 +47,4 @@ public:
|
|||
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -12,46 +12,6 @@ namespace { // Make everything here private
|
|||
namespace SIMDJSON_IMPLEMENTATION {
|
||||
namespace stage2 {
|
||||
|
||||
#ifdef SIMDJSON_USE_COMPUTED_GOTO
|
||||
#define INIT_ADDRESSES() { &&array_begin, &&array_continue, &&error, &&finish, &&object_begin, &&object_continue }
|
||||
#define GOTO(address) { goto *(address); }
|
||||
#define CONTINUE(address) { goto *(address); }
|
||||
#else // SIMDJSON_USE_COMPUTED_GOTO
|
||||
#define INIT_ADDRESSES() { '[', 'a', 'e', 'f', '{', 'o' };
|
||||
#define GOTO(address) \
|
||||
{ \
|
||||
switch(address) { \
|
||||
case '[': goto array_begin; \
|
||||
case 'a': goto array_continue; \
|
||||
case 'e': goto error; \
|
||||
case 'f': goto finish; \
|
||||
case '{': goto object_begin; \
|
||||
case 'o': goto object_continue; \
|
||||
} \
|
||||
}
|
||||
// For the more constrained end_xxx() situation
|
||||
#define CONTINUE(address) \
|
||||
{ \
|
||||
switch(address) { \
|
||||
case 'a': goto array_continue; \
|
||||
case 'o': goto object_continue; \
|
||||
case 'f': goto finish; \
|
||||
} \
|
||||
}
|
||||
#endif // SIMDJSON_USE_COMPUTED_GOTO
|
||||
|
||||
struct unified_machine_addresses {
|
||||
ret_address_t array_begin;
|
||||
ret_address_t array_continue;
|
||||
ret_address_t error;
|
||||
ret_address_t finish;
|
||||
ret_address_t object_begin;
|
||||
ret_address_t object_continue;
|
||||
};
|
||||
|
||||
#undef FAIL_IF
|
||||
#define FAIL_IF(EXPR) { if (EXPR) { return addresses.error; } }
|
||||
|
||||
struct structural_parser : structural_iterator {
|
||||
/** Lets you append to the tape */
|
||||
tape_writer tape;
|
||||
|
@ -67,30 +27,30 @@ struct structural_parser : structural_iterator {
|
|||
current_string_buf_loc{parser.doc->string_buf.get()} {
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool start_scope(ret_address_t continue_state) {
|
||||
WARN_UNUSED really_inline bool start_scope(bool parent_is_array) {
|
||||
parser.containing_scope[depth].tape_index = next_tape_index();
|
||||
parser.containing_scope[depth].count = 0;
|
||||
tape.skip(); // We don't actually *write* the start element until the end.
|
||||
parser.ret_address[depth] = continue_state;
|
||||
parser.is_array[depth] = parent_is_array;
|
||||
depth++;
|
||||
bool exceeded_max_depth = depth >= parser.max_depth();
|
||||
if (exceeded_max_depth) { log_error("Exceeded max depth!"); }
|
||||
return exceeded_max_depth;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool start_document(ret_address_t continue_state) {
|
||||
WARN_UNUSED really_inline bool start_document() {
|
||||
log_start_value("document");
|
||||
return start_scope(continue_state);
|
||||
return start_scope(false);
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool start_object(ret_address_t continue_state) {
|
||||
WARN_UNUSED really_inline bool start_object(bool parent_is_array) {
|
||||
log_start_value("object");
|
||||
return start_scope(continue_state);
|
||||
return start_scope(parent_is_array);
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool start_array(ret_address_t continue_state) {
|
||||
WARN_UNUSED really_inline bool start_array(bool parent_is_array) {
|
||||
log_start_value("array");
|
||||
return start_scope(continue_state);
|
||||
return start_scope(parent_is_array);
|
||||
}
|
||||
|
||||
// this function is responsible for annotating the start of the scope
|
||||
|
@ -173,7 +133,7 @@ struct structural_parser : structural_iterator {
|
|||
return parse_number(current());
|
||||
}
|
||||
|
||||
really_inline bool parse_number_with_space_terminated_copy() {
|
||||
really_inline bool parse_root_number() {
|
||||
/**
|
||||
* We need to make a copy to make sure that the string is space terminated.
|
||||
* This is not about padding the input, which should already padded up
|
||||
|
@ -198,41 +158,47 @@ struct structural_parser : structural_iterator {
|
|||
free(copy);
|
||||
return result;
|
||||
}
|
||||
WARN_UNUSED really_inline ret_address_t parse_value(const unified_machine_addresses &addresses, ret_address_t continue_state) {
|
||||
switch (advance_char()) {
|
||||
case '"':
|
||||
FAIL_IF( parse_string() );
|
||||
return continue_state;
|
||||
case 't':
|
||||
log_value("true");
|
||||
FAIL_IF( !atomparsing::is_valid_true_atom(current()) );
|
||||
tape.append(0, internal::tape_type::TRUE_VALUE);
|
||||
return continue_state;
|
||||
case 'f':
|
||||
log_value("false");
|
||||
FAIL_IF( !atomparsing::is_valid_false_atom(current()) );
|
||||
tape.append(0, internal::tape_type::FALSE_VALUE);
|
||||
return continue_state;
|
||||
case 'n':
|
||||
log_value("null");
|
||||
FAIL_IF( !atomparsing::is_valid_null_atom(current()) );
|
||||
tape.append(0, internal::tape_type::NULL_VALUE);
|
||||
return continue_state;
|
||||
case '-':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
FAIL_IF( parse_number() );
|
||||
return continue_state;
|
||||
case '{':
|
||||
FAIL_IF( start_object(continue_state) );
|
||||
return addresses.object_begin;
|
||||
case '[':
|
||||
FAIL_IF( start_array(continue_state) );
|
||||
return addresses.array_begin;
|
||||
default:
|
||||
log_error("Non-value found when value was expected!");
|
||||
return addresses.error;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_true_atom() {
|
||||
log_value("true");
|
||||
if (!atomparsing::is_valid_true_atom(current())) { return true; }
|
||||
tape.append(0, internal::tape_type::TRUE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_root_true_atom() {
|
||||
log_value("true");
|
||||
if (!atomparsing::is_valid_true_atom(current(), remaining_len())) { return true; }
|
||||
tape.append(0, internal::tape_type::TRUE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_false_atom() {
|
||||
log_value("false");
|
||||
if (!atomparsing::is_valid_false_atom(current())) { return true; }
|
||||
tape.append(0, internal::tape_type::FALSE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_root_false_atom() {
|
||||
log_value("false");
|
||||
if (!atomparsing::is_valid_false_atom(current(), remaining_len())) { return true; }
|
||||
tape.append(0, internal::tape_type::FALSE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_null_atom() {
|
||||
log_value("null");
|
||||
if (!atomparsing::is_valid_null_atom(current())) { return true; }
|
||||
tape.append(0, internal::tape_type::NULL_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline bool parse_root_null_atom() {
|
||||
log_value("null");
|
||||
if (!atomparsing::is_valid_null_atom(current(), remaining_len())) { return true; }
|
||||
tape.append(0, internal::tape_type::NULL_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline error_code finish() {
|
||||
|
@ -248,16 +214,14 @@ struct structural_parser : structural_iterator {
|
|||
}
|
||||
|
||||
WARN_UNUSED really_inline error_code error() {
|
||||
/* We do not need the next line because this is done by parser.init_stage2(),
|
||||
* pessimistically.
|
||||
* parser.is_valid = false;
|
||||
* At this point in the code, we have all the time in the world.
|
||||
* Note that we know exactly where we are in the document so we could,
|
||||
* without any overhead on the processing code, report a specific
|
||||
* location.
|
||||
* We could even trigger special code paths to assess what happened
|
||||
* carefully,
|
||||
* all without any added cost. */
|
||||
// At this point in the code, we have all the time in the world.
|
||||
// Note that we know exactly where we are in the document so we could,
|
||||
// without any overhead on the processing code, report a specific
|
||||
// location.
|
||||
// We could even trigger special code paths to assess what happened
|
||||
// carefully,
|
||||
// all without any added cost.
|
||||
//
|
||||
if (depth >= parser.max_depth()) {
|
||||
return parser.error = DEPTH_ERROR;
|
||||
}
|
||||
|
@ -292,7 +256,7 @@ struct structural_parser : structural_iterator {
|
|||
parser.error = UNINITIALIZED;
|
||||
}
|
||||
|
||||
WARN_UNUSED really_inline error_code start(ret_address_t finish_state) {
|
||||
WARN_UNUSED really_inline error_code start() {
|
||||
// If there are no structurals left, return EMPTY
|
||||
if (at_end(parser.n_structural_indexes)) {
|
||||
return parser.error = EMPTY;
|
||||
|
@ -300,7 +264,7 @@ struct structural_parser : structural_iterator {
|
|||
|
||||
init();
|
||||
// Push the root scope (there is always at least one scope)
|
||||
if (start_document(finish_state)) {
|
||||
if (start_document()) {
|
||||
return parser.error = DEPTH_ERROR;
|
||||
}
|
||||
return SUCCESS;
|
||||
|
@ -329,17 +293,11 @@ struct structural_parser : structural_iterator {
|
|||
}
|
||||
}; // struct structural_parser
|
||||
|
||||
// Redefine FAIL_IF to use goto since it'll be used inside the function now
|
||||
#undef FAIL_IF
|
||||
#define FAIL_IF(EXPR) { if (EXPR) { goto error; } }
|
||||
|
||||
|
||||
template<bool STREAMING>
|
||||
WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_parser, dom::document &doc) noexcept {
|
||||
WARN_UNUSED static really_inline error_code parse_structurals(dom_parser_implementation &dom_parser, dom::document &doc) noexcept {
|
||||
dom_parser.doc = &doc;
|
||||
static constexpr stage2::unified_machine_addresses addresses = INIT_ADDRESSES();
|
||||
stage2::structural_parser parser(dom_parser, STREAMING ? dom_parser.next_structural_index : 0);
|
||||
error_code result = parser.start(addresses.finish);
|
||||
error_code result = parser.start();
|
||||
if (result) { return result; }
|
||||
|
||||
//
|
||||
|
@ -347,10 +305,10 @@ WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_p
|
|||
//
|
||||
switch (parser.current_char()) {
|
||||
case '{':
|
||||
FAIL_IF( parser.start_object(addresses.finish) );
|
||||
if ( parser.start_object(false) ) { goto error; };
|
||||
goto object_begin;
|
||||
case '[':
|
||||
FAIL_IF( parser.start_array(addresses.finish) );
|
||||
if ( parser.start_array(false) ) { goto error; }
|
||||
// Make sure the outer 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) {
|
||||
|
@ -359,31 +317,17 @@ WARN_UNUSED static error_code parse_structurals(dom_parser_implementation &dom_p
|
|||
}
|
||||
}
|
||||
goto array_begin;
|
||||
case '"':
|
||||
FAIL_IF( parser.parse_string() );
|
||||
goto finish;
|
||||
case 't':
|
||||
parser.log_value("true");
|
||||
FAIL_IF( !atomparsing::is_valid_true_atom(parser.current(), parser.remaining_len()) );
|
||||
parser.tape.append(0, internal::tape_type::TRUE_VALUE);
|
||||
goto finish;
|
||||
case 'f':
|
||||
parser.log_value("false");
|
||||
FAIL_IF( !atomparsing::is_valid_false_atom(parser.current(), parser.remaining_len()) );
|
||||
parser.tape.append(0, internal::tape_type::FALSE_VALUE);
|
||||
goto finish;
|
||||
case 'n':
|
||||
parser.log_value("null");
|
||||
FAIL_IF( !atomparsing::is_valid_null_atom(parser.current(), parser.remaining_len()) );
|
||||
parser.tape.append(0, internal::tape_type::NULL_VALUE);
|
||||
goto finish;
|
||||
case '"': if ( parser.parse_string() ) { goto error; }; goto finish;
|
||||
case 't': if ( parser.parse_root_true_atom() ) { goto error; }; goto finish;
|
||||
case 'f': if ( parser.parse_root_false_atom() ) { goto error; }; goto finish;
|
||||
case 'n': if ( parser.parse_root_null_atom() ) { goto error; }; goto finish;
|
||||
case '-':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
// Next line used to be an interesting functional programming exercise with
|
||||
// a lambda that gets passed to another function via a closure. This would confuse the
|
||||
// clangcl compiler under Visual Studio 2019 (recent release).
|
||||
FAIL_IF(parser.parse_number_with_space_terminated_copy());
|
||||
if ( parser.parse_root_number() ) { goto error; }
|
||||
goto finish;
|
||||
default:
|
||||
parser.log_error("Document starts with a non-value character");
|
||||
|
@ -397,7 +341,7 @@ object_begin:
|
|||
switch (parser.advance_char()) {
|
||||
case '"': {
|
||||
parser.increment_count();
|
||||
FAIL_IF( parser.parse_string(true) );
|
||||
if ( parser.parse_string(true) ) { goto error; }
|
||||
goto object_key_state;
|
||||
}
|
||||
case '}':
|
||||
|
@ -409,15 +353,29 @@ object_begin:
|
|||
}
|
||||
|
||||
object_key_state:
|
||||
if (parser.advance_char() != ':' ) { parser.log_error("Missing colon after key in object"); goto error; }
|
||||
GOTO( parser.parse_value(addresses, addresses.object_continue) );
|
||||
if (unlikely( parser.advance_char() != ':' )) { parser.log_error("Missing colon after key in object"); goto error; }
|
||||
switch (parser.advance_char()) {
|
||||
case '{': if ( parser.start_object(false) ) { goto error; }; goto object_begin;
|
||||
case '[': if ( parser.start_array(false) ) { goto error; }; goto array_begin;
|
||||
case '"': if ( parser.parse_string() ) { goto error; }; break;
|
||||
case 't': if ( parser.parse_true_atom() ) { goto error; }; break;
|
||||
case 'f': if ( parser.parse_false_atom() ) { goto error; }; break;
|
||||
case 'n': if ( parser.parse_null_atom() ) { goto error; }; break;
|
||||
case '-':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if ( parser.parse_number() ) { goto error; }; break;
|
||||
default:
|
||||
parser.log_error("Non-value found when value was expected!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
object_continue:
|
||||
switch (parser.advance_char()) {
|
||||
case ',':
|
||||
parser.increment_count();
|
||||
if (parser.advance_char() != '"' ) { parser.log_error("Key string missing at beginning of field in object"); goto error; }
|
||||
FAIL_IF( parser.parse_string(true) );
|
||||
if (unlikely( parser.advance_char() != '"' )) { parser.log_error("Key string missing at beginning of field in object"); goto error; }
|
||||
if ( parser.parse_string(true) ) { goto error; }
|
||||
goto object_key_state;
|
||||
case '}':
|
||||
parser.end_object();
|
||||
|
@ -428,7 +386,9 @@ object_continue:
|
|||
}
|
||||
|
||||
scope_end:
|
||||
CONTINUE( parser.parser.ret_address[parser.depth] );
|
||||
if (parser.depth == 1) { goto finish; }
|
||||
if (parser.parser.is_array[parser.depth]) { goto array_continue; }
|
||||
goto object_continue;
|
||||
|
||||
//
|
||||
// Array parser states
|
||||
|
@ -442,9 +402,21 @@ array_begin:
|
|||
parser.increment_count();
|
||||
|
||||
main_array_switch:
|
||||
/* we call update char on all paths in, so we can peek at parser.c on the
|
||||
* on paths that can accept a close square brace (post-, and at start) */
|
||||
GOTO( parser.parse_value(addresses, addresses.array_continue) );
|
||||
switch (parser.advance_char()) {
|
||||
case '{': if ( parser.start_object(true) ) { goto error; }; goto object_begin;
|
||||
case '[': if ( parser.start_array(true) ) { goto error; }; goto array_begin;
|
||||
case '"': if ( parser.parse_string() ) { goto error; }; break;
|
||||
case 't': if ( parser.parse_true_atom() ) { goto error; }; break;
|
||||
case 'f': if ( parser.parse_false_atom() ) { goto error; }; break;
|
||||
case 'n': if ( parser.parse_null_atom() ) { goto error; }; break;
|
||||
case '-':
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
if ( parser.parse_number() ) { goto error; }; break;
|
||||
default:
|
||||
parser.log_error("Non-value found when value was expected!");
|
||||
goto error;
|
||||
}
|
||||
|
||||
array_continue:
|
||||
switch (parser.advance_char()) {
|
||||
|
@ -468,4 +440,4 @@ error:
|
|||
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -100,4 +100,4 @@ really_inline void tape_writer::write(uint64_t &tape_loc, uint64_t val, internal
|
|||
|
||||
} // namespace stage2
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
|
|
@ -54,6 +54,6 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_HASWELL_BITMANIPULATION_H
|
||||
|
|
|
@ -18,6 +18,6 @@ really_inline uint64_t prefix_xor(const uint64_t bitmask) {
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_HASWELL_BITMASK_H
|
||||
|
|
|
@ -65,7 +65,7 @@ really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, c
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage1/utf8_lookup4_algorithm.h"
|
||||
#include "generic/stage1/json_structural_indexer.h"
|
||||
|
@ -130,6 +130,6 @@ WARN_UNUSED error_code dom_parser_implementation::parse(const uint8_t *_buf, siz
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "haswell/end_implementation.h"
|
||||
|
|
|
@ -17,7 +17,7 @@ WARN_UNUSED error_code implementation::create_dom_parser_implementation(
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "haswell/end_implementation.h"
|
||||
|
||||
|
|
|
@ -27,6 +27,6 @@ public:
|
|||
};
|
||||
|
||||
} // namespace haswell
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_HASWELL_IMPLEMENTATION_H
|
|
@ -23,7 +23,7 @@ static really_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars)
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#define SWAR_NUMBER_PARSING
|
||||
|
||||
|
|
|
@ -349,6 +349,6 @@ namespace simd {
|
|||
} // namespace simd
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_HASWELL_SIMD_H
|
||||
|
|
|
@ -39,7 +39,7 @@ really_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage2/stringparsing.h"
|
||||
|
||||
|
|
|
@ -63,6 +63,6 @@ really_inline bool add_overflow(uint64_t value1, uint64_t value2,
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_WESTMERE_BITMANIPULATION_H
|
||||
|
|
|
@ -18,6 +18,6 @@ really_inline uint64_t prefix_xor(const uint64_t bitmask) {
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_WESTMERE_BITMASK_H
|
||||
|
|
|
@ -70,7 +70,7 @@ really_inline simd8<bool> must_be_2_3_continuation(const simd8<uint8_t> prev2, c
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage1/utf8_lookup4_algorithm.h"
|
||||
#include "generic/stage1/json_structural_indexer.h"
|
||||
|
@ -136,6 +136,6 @@ WARN_UNUSED error_code dom_parser_implementation::parse(const uint8_t *_buf, siz
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "westmere/end_implementation.h"
|
||||
|
|
|
@ -17,6 +17,6 @@ WARN_UNUSED error_code implementation::create_dom_parser_implementation(
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "westmere/end_implementation.h"
|
|
@ -25,6 +25,6 @@ public:
|
|||
};
|
||||
|
||||
} // namespace westmere
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_WESTMERE_IMPLEMENTATION_H
|
|
@ -23,7 +23,7 @@ static really_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars)
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#define SWAR_NUMBER_PARSING
|
||||
|
||||
|
|
|
@ -328,6 +328,6 @@ namespace simd {
|
|||
|
||||
} // namespace simd
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#endif // SIMDJSON_WESTMERE_SIMD_INPUT_H
|
||||
|
|
|
@ -37,7 +37,7 @@ really_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8
|
|||
}
|
||||
|
||||
} // namespace SIMDJSON_IMPLEMENTATION
|
||||
} // namespace {
|
||||
} // unnamed namespace
|
||||
|
||||
#include "generic/stage2/stringparsing.h"
|
||||
|
||||
|
|
Loading…
Reference in New Issue