Skip to content

Commit 4551e60

Browse files
committed
Don't write start object/array until the end
1 parent ea842e7 commit 4551e60

File tree

1 file changed

+27
-23
lines changed

1 file changed

+27
-23
lines changed

src/generic/stage2/structural_parser.h

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,21 @@ struct number_writer {
5151
parser &doc_parser;
5252

5353
really_inline void write_s64(int64_t value) noexcept {
54-
write_tape(0, internal::tape_type::INT64);
54+
append_tape(0, internal::tape_type::INT64);
5555
std::memcpy(&doc_parser.doc.tape[doc_parser.current_loc], &value, sizeof(value));
5656
++doc_parser.current_loc;
5757
}
5858
really_inline void write_u64(uint64_t value) noexcept {
59-
write_tape(0, internal::tape_type::UINT64);
59+
append_tape(0, internal::tape_type::UINT64);
6060
doc_parser.doc.tape[doc_parser.current_loc++] = value;
6161
}
6262
really_inline void write_double(double value) noexcept {
63-
write_tape(0, internal::tape_type::DOUBLE);
63+
append_tape(0, internal::tape_type::DOUBLE);
6464
static_assert(sizeof(value) == sizeof(doc_parser.doc.tape[doc_parser.current_loc]), "mismatch size");
6565
memcpy(&doc_parser.doc.tape[doc_parser.current_loc++], &value, sizeof(double));
6666
// doc.tape[doc.current_loc++] = *((uint64_t *)&d);
6767
}
68-
really_inline void write_tape(uint64_t val, internal::tape_type t) noexcept {
68+
really_inline void append_tape(uint64_t val, internal::tape_type t) noexcept {
6969
doc_parser.doc.tape[doc_parser.current_loc++] = val | ((uint64_t(char(t))) << 56);
7070
}
7171
}; // struct number_writer
@@ -84,10 +84,10 @@ struct structural_parser {
8484
uint32_t next_structural = 0
8585
) : structurals(buf, len, _doc_parser.structural_indexes.get(), next_structural), doc_parser{_doc_parser}, depth{0} {}
8686

87-
WARN_UNUSED really_inline bool start_scope(internal::tape_type type, ret_address continue_state) {
87+
WARN_UNUSED really_inline bool start_scope(ret_address continue_state) {
8888
doc_parser.containing_scope[depth].tape_index = doc_parser.current_loc;
8989
doc_parser.containing_scope[depth].count = 0;
90-
write_tape(0, type); // if the document is correct, this gets rewritten later
90+
doc_parser.current_loc++; // We don't actually *write* the start element until the end.
9191
doc_parser.ret_address[depth] = continue_state;
9292
depth++;
9393
bool exceeded_max_depth = depth >= doc_parser.max_depth();
@@ -97,51 +97,55 @@ struct structural_parser {
9797

9898
WARN_UNUSED really_inline bool start_document(ret_address continue_state) {
9999
log_start_value("document");
100-
return start_scope(internal::tape_type::ROOT, continue_state);
100+
return start_scope(continue_state);
101101
}
102102

103103
WARN_UNUSED really_inline bool start_object(ret_address continue_state) {
104104
log_start_value("object");
105-
return start_scope(internal::tape_type::START_OBJECT, continue_state);
105+
return start_scope(continue_state);
106106
}
107107

108108
WARN_UNUSED really_inline bool start_array(ret_address continue_state) {
109109
log_start_value("array");
110-
return start_scope(internal::tape_type::START_ARRAY, continue_state);
110+
return start_scope(continue_state);
111111
}
112112

113113
// this function is responsible for annotating the start of the scope
114-
really_inline void end_scope(internal::tape_type type) noexcept {
114+
really_inline void end_scope(internal::tape_type start, internal::tape_type end) noexcept {
115115
depth--;
116116
// write our doc.tape location to the header scope
117117
// The root scope gets written *at* the previous location.
118-
write_tape(doc_parser.containing_scope[depth].tape_index, type);
118+
append_tape(doc_parser.containing_scope[depth].tape_index, end);
119119
// count can overflow if it exceeds 24 bits... so we saturate
120120
// the convention being that a cnt of 0xffffff or more is undetermined in value (>= 0xffffff).
121121
const uint32_t start_tape_index = doc_parser.containing_scope[depth].tape_index;
122122
const uint32_t count = doc_parser.containing_scope[depth].count;
123123
const uint32_t cntsat = count > 0xFFFFFF ? 0xFFFFFF : count;
124124
// This is a load and an OR. It would be possible to just write once at doc.tape[d.tape_index]
125-
doc_parser.doc.tape[start_tape_index] |= doc_parser.current_loc | (uint64_t(cntsat) << 32);
125+
write_tape(start_tape_index, doc_parser.current_loc | (uint64_t(cntsat) << 32), start);
126126
}
127127

128128
really_inline void end_object() {
129129
log_end_value("object");
130-
end_scope(internal::tape_type::END_OBJECT);
130+
end_scope(internal::tape_type::START_OBJECT, internal::tape_type::END_OBJECT);
131131
}
132132
really_inline void end_array() {
133133
log_end_value("array");
134-
end_scope(internal::tape_type::END_ARRAY);
134+
end_scope(internal::tape_type::START_ARRAY, internal::tape_type::END_ARRAY);
135135
}
136136
really_inline void end_document() {
137137
log_end_value("document");
138-
end_scope(internal::tape_type::ROOT);
138+
end_scope(internal::tape_type::ROOT, internal::tape_type::ROOT);
139139
}
140140

141-
really_inline void write_tape(uint64_t val, internal::tape_type t) noexcept {
141+
really_inline void append_tape(uint64_t val, internal::tape_type t) noexcept {
142142
doc_parser.doc.tape[doc_parser.current_loc++] = val | ((uint64_t(char(t))) << 56);
143143
}
144144

145+
really_inline void write_tape(uint32_t loc, uint64_t val, internal::tape_type t) noexcept {
146+
doc_parser.doc.tape[loc] = val | ((uint64_t(char(t))) << 56);
147+
}
148+
145149
// increment_count increments the count of keys in an object or values in an array.
146150
// Note that if you are at the level of the values or elements, the count
147151
// must be increment in the preceding depth (depth-1) where the array or
@@ -152,7 +156,7 @@ struct structural_parser {
152156

153157
really_inline uint8_t *on_start_string() noexcept {
154158
// we advance the point, accounting for the fact that we have a NULL termination
155-
write_tape(current_string_buf_loc - doc_parser.doc.string_buf.get(), internal::tape_type::STRING);
159+
append_tape(current_string_buf_loc - doc_parser.doc.string_buf.get(), internal::tape_type::STRING);
156160
return current_string_buf_loc + sizeof(uint32_t);
157161
}
158162

@@ -196,17 +200,17 @@ struct structural_parser {
196200
case 't':
197201
log_value("true");
198202
if (!atomparsing::is_valid_true_atom(structurals.current())) { return true; }
199-
write_tape(0, internal::tape_type::TRUE_VALUE);
203+
append_tape(0, internal::tape_type::TRUE_VALUE);
200204
break;
201205
case 'f':
202206
log_value("false");
203207
if (!atomparsing::is_valid_false_atom(structurals.current())) { return true; }
204-
write_tape(0, internal::tape_type::FALSE_VALUE);
208+
append_tape(0, internal::tape_type::FALSE_VALUE);
205209
break;
206210
case 'n':
207211
log_value("null");
208212
if (!atomparsing::is_valid_null_atom(structurals.current())) { return true; }
209-
write_tape(0, internal::tape_type::NULL_VALUE);
213+
append_tape(0, internal::tape_type::NULL_VALUE);
210214
break;
211215
default:
212216
log_error("IMPOSSIBLE: unrecognized parse_atom structural character");
@@ -220,17 +224,17 @@ struct structural_parser {
220224
case 't':
221225
log_value("true");
222226
if (!atomparsing::is_valid_true_atom(structurals.current(), structurals.remaining_len())) { return true; }
223-
write_tape(0, internal::tape_type::TRUE_VALUE);
227+
append_tape(0, internal::tape_type::TRUE_VALUE);
224228
break;
225229
case 'f':
226230
log_value("false");
227231
if (!atomparsing::is_valid_false_atom(structurals.current(), structurals.remaining_len())) { return true; }
228-
write_tape(0, internal::tape_type::FALSE_VALUE);
232+
append_tape(0, internal::tape_type::FALSE_VALUE);
229233
break;
230234
case 'n':
231235
log_value("null");
232236
if (!atomparsing::is_valid_null_atom(structurals.current(), structurals.remaining_len())) { return true; }
233-
write_tape(0, internal::tape_type::NULL_VALUE);
237+
append_tape(0, internal::tape_type::NULL_VALUE);
234238
break;
235239
default:
236240
log_error("IMPOSSIBLE: unrecognized parse_atom structural character");

0 commit comments

Comments
 (0)