Separate interface from implementation to make interface clearer

This commit is contained in:
John Keiser 2020-08-12 09:38:11 -07:00
parent 15eb1ad922
commit bdfa8aca28
2 changed files with 300 additions and 249 deletions

View File

@ -14,52 +14,20 @@ public:
template<bool STREAMING, typename V> template<bool STREAMING, typename V>
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code walk_document(V &visitor) noexcept; SIMDJSON_WARN_UNUSED simdjson_really_inline error_code walk_document(V &visitor) noexcept;
// Start a structural simdjson_really_inline json_iterator(dom_parser_implementation &_dom_parser, size_t start_structural_index);
simdjson_really_inline json_iterator(dom_parser_implementation &_dom_parser, size_t start_structural_index)
: buf{_dom_parser.buf},
next_structural{&_dom_parser.structural_indexes[start_structural_index]},
dom_parser{_dom_parser} {
}
// Get the buffer position of the current structural character // Get the buffer position of the current structural character
simdjson_really_inline char peek_next_char() { simdjson_really_inline char peek_next_char() const noexcept;
return buf[*(next_structural)]; simdjson_really_inline const uint8_t *advance() noexcept;
} simdjson_really_inline size_t remaining_len() const noexcept;
simdjson_really_inline const uint8_t *advance() { simdjson_really_inline bool at_end() const noexcept;
return &buf[*(next_structural++)]; simdjson_really_inline bool at_beginning() const noexcept;
} simdjson_really_inline uint8_t last_structural() const noexcept;
simdjson_really_inline size_t remaining_len() {
return dom_parser.len - *(next_structural-1);
}
simdjson_really_inline bool at_end() { simdjson_really_inline void log_value(const char *type) const noexcept;
return next_structural == &dom_parser.structural_indexes[dom_parser.n_structural_indexes]; simdjson_really_inline void log_start_value(const char *type) const noexcept;
} simdjson_really_inline void log_end_value(const char *type) const noexcept;
simdjson_really_inline bool at_beginning() { simdjson_really_inline void log_error(const char *error) const noexcept;
return next_structural == dom_parser.structural_indexes.get();
}
simdjson_really_inline void log_value(const char *type) {
logger::log_line(*this, "", type, "");
}
simdjson_really_inline void log_start_value(const char *type) {
logger::log_line(*this, "+", type, "");
if (logger::LOG_ENABLED) { logger::log_depth++; }
}
simdjson_really_inline void log_end_value(const char *type) {
if (logger::LOG_ENABLED) { logger::log_depth--; }
logger::log_line(*this, "-", type, "");
}
simdjson_really_inline void log_error(const char *error) {
logger::log_line(*this, "", "ERROR", error);
}
simdjson_really_inline uint8_t last_structural() {
return buf[dom_parser.structural_indexes[dom_parser.n_structural_indexes - 1]];
}
}; };
template<bool STREAMING, typename V> template<bool STREAMING, typename V>
@ -190,6 +158,50 @@ document_end:
} // walk_document() } // walk_document()
simdjson_really_inline json_iterator::json_iterator(dom_parser_implementation &_dom_parser, size_t start_structural_index)
: buf{_dom_parser.buf},
next_structural{&_dom_parser.structural_indexes[start_structural_index]},
dom_parser{_dom_parser} {
}
simdjson_really_inline char json_iterator::peek_next_char() const noexcept {
return buf[*(next_structural)];
}
simdjson_really_inline const uint8_t *json_iterator::advance() noexcept {
return &buf[*(next_structural++)];
}
simdjson_really_inline size_t json_iterator::remaining_len() const noexcept {
return dom_parser.len - *(next_structural-1);
}
simdjson_really_inline bool json_iterator::at_end() const noexcept {
return next_structural == &dom_parser.structural_indexes[dom_parser.n_structural_indexes];
}
simdjson_really_inline bool json_iterator::at_beginning() const noexcept {
return next_structural == dom_parser.structural_indexes.get();
}
simdjson_really_inline uint8_t json_iterator::last_structural() const noexcept {
return buf[dom_parser.structural_indexes[dom_parser.n_structural_indexes - 1]];
}
simdjson_really_inline void json_iterator::log_value(const char *type) const noexcept {
logger::log_line(*this, "", type, "");
}
simdjson_really_inline void json_iterator::log_start_value(const char *type) const noexcept {
logger::log_line(*this, "+", type, "");
if (logger::LOG_ENABLED) { logger::log_depth++; }
}
simdjson_really_inline void json_iterator::log_end_value(const char *type) const noexcept {
if (logger::LOG_ENABLED) { logger::log_depth--; }
logger::log_line(*this, "-", type, "");
}
simdjson_really_inline void json_iterator::log_error(const char *error) const noexcept {
logger::log_line(*this, "", "ERROR", error);
}
} // namespace stage2 } // namespace stage2
} // namespace SIMDJSON_IMPLEMENTATION } // namespace SIMDJSON_IMPLEMENTATION
} // unnamed namespace } // unnamed namespace

View File

@ -9,6 +9,55 @@ namespace stage2 {
struct tape_builder { struct tape_builder {
template<bool STREAMING> template<bool STREAMING>
SIMDJSON_WARN_UNUSED static simdjson_really_inline error_code parse_document( SIMDJSON_WARN_UNUSED static simdjson_really_inline error_code parse_document(
dom_parser_implementation &dom_parser,
dom::document &doc) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_primitive(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_primitive(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_empty_object(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_empty_array(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_document_start(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_object_start(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_array_start(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_object_end(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_array_end(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_document_end(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_key(json_iterator &iter, const uint8_t *key) noexcept;
// increment_count increments the count of keys in an object or values in an array.
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code increment_count(json_iterator &iter) noexcept;
simdjson_really_inline bool in_array(json_iterator &iter) noexcept;
private:
/** Next location to write to tape */
tape_writer tape;
/** Next write location in the string buf for stage 2 parsing */
uint8_t *current_string_buf_loc;
simdjson_really_inline tape_builder(dom::document &doc) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_string(json_iterator &iter, const uint8_t *value, bool key = false) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_number(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_number(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_true_atom(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_true_atom(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_false_atom(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_false_atom(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_null_atom(json_iterator &iter, const uint8_t *value) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_null_atom(json_iterator &iter, const uint8_t *value) noexcept;
simdjson_really_inline uint32_t next_tape_index(json_iterator &iter) const noexcept;
simdjson_really_inline void start_container(json_iterator &iter) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code end_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept;
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code empty_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept;
simdjson_really_inline uint8_t *on_start_string(json_iterator &iter) noexcept;
simdjson_really_inline void on_end_string(uint8_t *dst) noexcept;
}; // class tape_builder
template<bool STREAMING>
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::parse_document(
dom_parser_implementation &dom_parser, dom_parser_implementation &dom_parser,
dom::document &doc) noexcept { dom::document &doc) noexcept {
dom_parser.doc = &doc; dom_parser.doc = &doc;
@ -17,7 +66,7 @@ struct tape_builder {
return iter.walk_document<STREAMING>(builder); return iter.walk_document<STREAMING>(builder);
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_primitive(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_primitive(json_iterator &iter, const uint8_t *value) noexcept {
switch (*value) { switch (*value) {
case '"': return visit_string(iter, value); case '"': return visit_string(iter, value);
case 't': return visit_root_true_atom(iter, value); case 't': return visit_root_true_atom(iter, value);
@ -32,7 +81,7 @@ struct tape_builder {
return TAPE_ERROR; return TAPE_ERROR;
} }
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_primitive(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_primitive(json_iterator &iter, const uint8_t *value) noexcept {
switch (*value) { switch (*value) {
case '"': return visit_string(iter, value); case '"': return visit_string(iter, value);
case 't': return visit_true_atom(iter, value); case 't': return visit_true_atom(iter, value);
@ -47,71 +96,64 @@ struct tape_builder {
return TAPE_ERROR; return TAPE_ERROR;
} }
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_empty_object(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_empty_object(json_iterator &iter) noexcept {
iter.log_value("empty object"); iter.log_value("empty object");
return empty_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT); return empty_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT);
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_empty_array(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_empty_array(json_iterator &iter) noexcept {
iter.log_value("empty array"); iter.log_value("empty array");
return empty_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY); return empty_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY);
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_document_start(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_document_start(json_iterator &iter) noexcept {
iter.log_start_value("document"); iter.log_start_value("document");
start_container(iter); start_container(iter);
iter.dom_parser.is_array[iter.depth] = false; iter.dom_parser.is_array[iter.depth] = false;
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_object_start(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_object_start(json_iterator &iter) noexcept {
iter.log_start_value("object"); iter.log_start_value("object");
start_container(iter); start_container(iter);
iter.dom_parser.is_array[iter.depth] = false; iter.dom_parser.is_array[iter.depth] = false;
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_array_start(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_array_start(json_iterator &iter) noexcept {
iter.log_start_value("array"); iter.log_start_value("array");
start_container(iter); start_container(iter);
iter.dom_parser.is_array[iter.depth] = true; iter.dom_parser.is_array[iter.depth] = true;
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_object_end(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_object_end(json_iterator &iter) noexcept {
iter.log_end_value("object"); iter.log_end_value("object");
return end_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT); return end_container(iter, internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT);
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_array_end(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_array_end(json_iterator &iter) noexcept {
iter.log_end_value("array"); iter.log_end_value("array");
return end_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY); return end_container(iter, internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY);
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_document_end(json_iterator &iter) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_document_end(json_iterator &iter) noexcept {
iter.log_end_value("document"); iter.log_end_value("document");
constexpr uint32_t start_tape_index = 0; constexpr uint32_t start_tape_index = 0;
tape.append(start_tape_index, internal::tape_type::ROOT); tape.append(start_tape_index, internal::tape_type::ROOT);
tape_writer::write(iter.dom_parser.doc->tape[start_tape_index], next_tape_index(iter), internal::tape_type::ROOT); tape_writer::write(iter.dom_parser.doc->tape[start_tape_index], next_tape_index(iter), internal::tape_type::ROOT);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_key(json_iterator &iter, const uint8_t *key) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_key(json_iterator &iter, const uint8_t *key) noexcept {
return visit_string(iter, key, true); return visit_string(iter, key, true);
} }
// increment_count increments the count of keys in an object or values in an array. SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::increment_count(json_iterator &iter) noexcept {
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code increment_count(json_iterator &iter) {
iter.dom_parser.open_containers[iter.depth].count++; // we have a key value pair in the object at parser.dom_parser.depth - 1 iter.dom_parser.open_containers[iter.depth].count++; // we have a key value pair in the object at parser.dom_parser.depth - 1
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline bool in_array(json_iterator &iter) noexcept { simdjson_really_inline bool tape_builder::in_array(json_iterator &iter) noexcept {
return iter.dom_parser.is_array[iter.depth]; return iter.dom_parser.is_array[iter.depth];
} }
private: simdjson_really_inline tape_builder::tape_builder(dom::document &doc) noexcept : tape{doc.tape.get()}, current_string_buf_loc{doc.string_buf.get()} {}
/** Next location to write to tape */
tape_writer tape;
/** Next write location in the string buf for stage 2 parsing */
uint8_t *current_string_buf_loc;
simdjson_really_inline tape_builder(dom::document &doc) noexcept : tape{doc.tape.get()}, current_string_buf_loc{doc.string_buf.get()} {} SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_string(json_iterator &iter, const uint8_t *value, bool key) noexcept {
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_string(json_iterator &iter, const uint8_t *value, bool key = false) {
iter.log_value(key ? "key" : "string"); iter.log_value(key ? "key" : "string");
uint8_t *dst = on_start_string(iter); uint8_t *dst = on_start_string(iter);
dst = stringparsing::parse_string(value, dst); dst = stringparsing::parse_string(value, dst);
@ -123,13 +165,13 @@ private:
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_number(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("number"); iter.log_value("number");
if (!numberparsing::parse_number(value, tape)) { iter.log_error("Invalid number"); return NUMBER_ERROR; } if (!numberparsing::parse_number(value, tape)) { iter.log_error("Invalid number"); return NUMBER_ERROR; }
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_number(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {
// //
// We need to make a copy to make sure that the string is space terminated. // 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 // This is not about padding the input, which should already padded up
@ -144,9 +186,7 @@ private:
// documents made of single atoms. // documents made of single atoms.
// //
uint8_t *copy = static_cast<uint8_t *>(malloc(iter.remaining_len() + SIMDJSON_PADDING)); uint8_t *copy = static_cast<uint8_t *>(malloc(iter.remaining_len() + SIMDJSON_PADDING));
if (copy == nullptr) { if (copy == nullptr) { return MEMALLOC; }
return MEMALLOC;
}
memcpy(copy, value, iter.remaining_len()); memcpy(copy, value, iter.remaining_len());
memset(copy + iter.remaining_len(), ' ', SIMDJSON_PADDING); memset(copy + iter.remaining_len(), ' ', SIMDJSON_PADDING);
error_code error = visit_number(iter, copy); error_code error = visit_number(iter, copy);
@ -154,42 +194,42 @@ private:
return error; return error;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_true_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_true_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("true"); iter.log_value("true");
if (!atomparsing::is_valid_true_atom(value)) { return T_ATOM_ERROR; } if (!atomparsing::is_valid_true_atom(value)) { return T_ATOM_ERROR; }
tape.append(0, internal::tape_type::TRUE_VALUE); tape.append(0, internal::tape_type::TRUE_VALUE);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_true_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_true_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("true"); iter.log_value("true");
if (!atomparsing::is_valid_true_atom(value, iter.remaining_len())) { return T_ATOM_ERROR; } if (!atomparsing::is_valid_true_atom(value, iter.remaining_len())) { return T_ATOM_ERROR; }
tape.append(0, internal::tape_type::TRUE_VALUE); tape.append(0, internal::tape_type::TRUE_VALUE);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_false_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_false_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("false"); iter.log_value("false");
if (!atomparsing::is_valid_false_atom(value)) { return F_ATOM_ERROR; } if (!atomparsing::is_valid_false_atom(value)) { return F_ATOM_ERROR; }
tape.append(0, internal::tape_type::FALSE_VALUE); tape.append(0, internal::tape_type::FALSE_VALUE);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_false_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_false_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("false"); iter.log_value("false");
if (!atomparsing::is_valid_false_atom(value, iter.remaining_len())) { return F_ATOM_ERROR; } if (!atomparsing::is_valid_false_atom(value, iter.remaining_len())) { return F_ATOM_ERROR; }
tape.append(0, internal::tape_type::FALSE_VALUE); tape.append(0, internal::tape_type::FALSE_VALUE);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_null_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_null_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("null"); iter.log_value("null");
if (!atomparsing::is_valid_null_atom(value)) { return N_ATOM_ERROR; } if (!atomparsing::is_valid_null_atom(value)) { return N_ATOM_ERROR; }
tape.append(0, internal::tape_type::NULL_VALUE); tape.append(0, internal::tape_type::NULL_VALUE);
return SUCCESS; return SUCCESS;
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code visit_root_null_atom(json_iterator &iter, const uint8_t *value) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_null_atom(json_iterator &iter, const uint8_t *value) noexcept {
iter.log_value("null"); iter.log_value("null");
if (!atomparsing::is_valid_null_atom(value, iter.remaining_len())) { return N_ATOM_ERROR; } if (!atomparsing::is_valid_null_atom(value, iter.remaining_len())) { return N_ATOM_ERROR; }
tape.append(0, internal::tape_type::NULL_VALUE); tape.append(0, internal::tape_type::NULL_VALUE);
@ -198,24 +238,24 @@ private:
// private: // private:
simdjson_really_inline uint32_t next_tape_index(json_iterator &iter) { simdjson_really_inline uint32_t tape_builder::next_tape_index(json_iterator &iter) const noexcept {
return uint32_t(tape.next_tape_loc - iter.dom_parser.doc->tape.get()); return uint32_t(tape.next_tape_loc - iter.dom_parser.doc->tape.get());
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code empty_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::empty_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept {
auto start_index = next_tape_index(iter); auto start_index = next_tape_index(iter);
tape.append(start_index+2, start); tape.append(start_index+2, start);
tape.append(start_index, end); tape.append(start_index, end);
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline void start_container(json_iterator &iter) { simdjson_really_inline void tape_builder::start_container(json_iterator &iter) noexcept {
iter.dom_parser.open_containers[iter.depth].tape_index = next_tape_index(iter); iter.dom_parser.open_containers[iter.depth].tape_index = next_tape_index(iter);
iter.dom_parser.open_containers[iter.depth].count = 0; iter.dom_parser.open_containers[iter.depth].count = 0;
tape.skip(); // We don't actually *write* the start element until the end. tape.skip(); // We don't actually *write* the start element until the end.
} }
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code end_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept { SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::end_container(json_iterator &iter, internal::tape_type start, internal::tape_type end) noexcept {
// Write the ending tape element, pointing at the start location // Write the ending tape element, pointing at the start location
const uint32_t start_tape_index = iter.dom_parser.open_containers[iter.depth].tape_index; const uint32_t start_tape_index = iter.dom_parser.open_containers[iter.depth].tape_index;
tape.append(start_tape_index, end); tape.append(start_tape_index, end);
@ -228,13 +268,13 @@ private:
return SUCCESS; return SUCCESS;
} }
simdjson_really_inline uint8_t *on_start_string(json_iterator &iter) noexcept { simdjson_really_inline uint8_t *tape_builder::on_start_string(json_iterator &iter) noexcept {
// we advance the point, accounting for the fact that we have a NULL termination // we advance the point, accounting for the fact that we have a NULL termination
tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::STRING); tape.append(current_string_buf_loc - iter.dom_parser.doc->string_buf.get(), internal::tape_type::STRING);
return current_string_buf_loc + sizeof(uint32_t); return current_string_buf_loc + sizeof(uint32_t);
} }
simdjson_really_inline void on_end_string(uint8_t *dst) noexcept { simdjson_really_inline void tape_builder::on_end_string(uint8_t *dst) noexcept {
uint32_t str_length = uint32_t(dst - (current_string_buf_loc + sizeof(uint32_t))); uint32_t str_length = uint32_t(dst - (current_string_buf_loc + sizeof(uint32_t)));
// TODO check for overflow in case someone has a crazy string (>=4GB?) // TODO check for overflow in case someone has a crazy string (>=4GB?)
// But only add the overflow check when the document itself exceeds 4GB // But only add the overflow check when the document itself exceeds 4GB
@ -245,7 +285,6 @@ private:
*dst = 0; *dst = 0;
current_string_buf_loc = dst + 1; current_string_buf_loc = dst + 1;
} }
}; // class tape_builder
} // namespace stage2 } // namespace stage2
} // namespace SIMDJSON_IMPLEMENTATION } // namespace SIMDJSON_IMPLEMENTATION