Skip to content

Commit 57eb554

Browse files
committed
Cache string value locally
1 parent abd1399 commit 57eb554

File tree

1 file changed

+52
-40
lines changed

1 file changed

+52
-40
lines changed

src/generic/stage2/json_iterator.h

Lines changed: 52 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ class json_iterator {
1010
uint32_t *next_structural;
1111
dom_parser_implementation &dom_parser;
1212
uint32_t depth{0};
13-
const uint8_t *value{}; // Used to keep a value around between states
1413

1514
template<bool STREAMING, typename T>
1615
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code walk_document(T &visitor) noexcept;
@@ -26,9 +25,8 @@ class json_iterator {
2625
simdjson_really_inline char peek_next_char() {
2726
return buf[*(next_structural)];
2827
}
29-
simdjson_really_inline char advance() {
30-
value = &buf[*(next_structural++)];
31-
return *value;
28+
simdjson_really_inline const uint8_t *advance() {
29+
return &buf[*(next_structural++)];
3230
}
3331
simdjson_really_inline size_t remaining_len() {
3432
return dom_parser.len - *(next_structural-1);
@@ -97,30 +95,32 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code json_iterator::walk_docum
9795
//
9896
// Read first value
9997
//
100-
advance();
98+
{
99+
auto value = advance();
100+
101+
// Make sure the outer hash or array is closed before continuing; otherwise, there are ways we
102+
// could get into memory corruption. See https://github.com/simdjson/simdjson/issues/906
103+
if (!STREAMING) {
104+
switch (*value) {
105+
case '{':
106+
if (last_structural() != '}') {
107+
return TAPE_ERROR;
108+
}
109+
break;
110+
case '[':
111+
if (last_structural() != ']') {
112+
return TAPE_ERROR;
113+
}
114+
break;
115+
}
116+
}
101117

102-
// Make sure the outer hash or array is closed before continuing; otherwise, there are ways we
103-
// could get into memory corruption. See https://github.com/simdjson/simdjson/issues/906
104-
if (!STREAMING) {
105118
switch (*value) {
106-
case '{':
107-
if (last_structural() != '}') {
108-
return TAPE_ERROR;
109-
}
110-
break;
111-
case '[':
112-
if (last_structural() != ']') {
113-
return TAPE_ERROR;
114-
}
115-
break;
119+
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
120+
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
121+
default: SIMDJSON_TRY( visitor.root_primitive(*this, value) ); break;
116122
}
117123
}
118-
119-
switch (*value) {
120-
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
121-
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
122-
default: SIMDJSON_TRY( visitor.root_primitive(*this, value) ); break;
123-
}
124124
goto document_end;
125125

126126
//
@@ -131,24 +131,33 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code json_iterator::walk_docum
131131
if (depth >= dom_parser.max_depth()) { log_error("Exceeded max depth!"); return DEPTH_ERROR; }
132132
SIMDJSON_TRY( visitor.start_object(*this) );
133133

134-
if (advance() != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
135-
visitor.increment_count(*this);
136-
SIMDJSON_TRY( visitor.key(*this, value) );
134+
{
135+
auto key = advance();
136+
if (*key != '"') { log_error("Object does not start with a key"); return TAPE_ERROR; }
137+
visitor.increment_count(*this);
138+
SIMDJSON_TRY( visitor.key(*this, key) );
139+
}
137140

138141
object_field:
139-
if (simdjson_unlikely( advance() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
140-
switch (advance()) {
141-
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
142-
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
143-
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
142+
if (simdjson_unlikely( *advance() != ':' )) { log_error("Missing colon after key in object"); return TAPE_ERROR; }
143+
{
144+
auto value = advance();
145+
switch (*value) {
146+
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
147+
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
148+
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
149+
}
144150
}
145151

146152
object_continue:
147-
switch (advance()) {
153+
switch (*advance()) {
148154
case ',':
149155
visitor.increment_count(*this);
150-
if (simdjson_unlikely( advance() != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
151-
SIMDJSON_TRY( visitor.key(*this, value) );
156+
{
157+
auto key = advance();
158+
if (simdjson_unlikely( *key != '"' )) { log_error("Key string missing at beginning of field in object"); return TAPE_ERROR; }
159+
SIMDJSON_TRY( visitor.key(*this, key) );
160+
}
152161
goto object_field;
153162
case '}': SIMDJSON_TRY( visitor.end_object(*this) ); goto scope_end;
154163
default: log_error("No comma between object fields"); return TAPE_ERROR;
@@ -170,14 +179,17 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code json_iterator::walk_docum
170179
visitor.increment_count(*this);
171180

172181
array_value:
173-
switch (advance()) {
174-
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
175-
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
176-
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
182+
{
183+
auto value = advance();
184+
switch (*value) {
185+
case '{': if (!empty_object(visitor)) { goto object_begin; }; break;
186+
case '[': if (!empty_array(visitor)) { goto array_begin; }; break;
187+
default: SIMDJSON_TRY( visitor.primitive(*this, value) ); break;
188+
}
177189
}
178190

179191
array_continue:
180-
switch (advance()) {
192+
switch (*advance()) {
181193
case ',': visitor.increment_count(*this); goto array_value;
182194
case ']': SIMDJSON_TRY( visitor.end_array(*this) ); goto scope_end;
183195
default: log_error("Missing comma between array values"); return TAPE_ERROR;

0 commit comments

Comments
 (0)