@@ -62,8 +62,6 @@ struct structural_parser {
62
62
WARN_UNUSED really_inline bool start_scope (internal::tape_type type) {
63
63
bool exceeded_max_depth = depth >= doc_parser.max_depth ();
64
64
if (exceeded_max_depth) { log_error (" Exceeded max depth!" ); return true ; }
65
- doc_parser.containing_scope [depth].tape_index = doc_parser.current_loc ;
66
- doc_parser.containing_scope [depth].count = 0 ;
67
65
write_tape (0 , type); // if the document is correct, this gets rewritten later
68
66
return false ;
69
67
}
@@ -84,44 +82,34 @@ struct structural_parser {
84
82
}
85
83
86
84
// this function is responsible for annotating the start of the scope
87
- really_inline void end_scope (internal::tape_type type) noexcept {
85
+ really_inline void end_scope (internal::tape_type type, uint32_t start_loc, uint32_t count ) noexcept {
88
86
// write our doc.tape location to the header scope
89
87
// The root scope gets written *at* the previous location.
90
- write_tape (doc_parser. containing_scope [depth]. tape_index , type);
88
+ write_tape (start_loc , type);
91
89
// count can overflow if it exceeds 24 bits... so we saturate
92
90
// the convention being that a cnt of 0xffffff or more is undetermined in value (>= 0xffffff).
93
- const uint32_t start_tape_index = doc_parser.containing_scope [depth].tape_index ;
94
- const uint32_t count = doc_parser.containing_scope [depth].count ;
95
91
const uint32_t cntsat = count > 0xFFFFFF ? 0xFFFFFF : count;
96
92
// This is a load and an OR. It would be possible to just write once at doc.tape[d.tape_index]
97
- doc_parser.doc .tape [start_tape_index ] |= doc_parser.current_loc | (uint64_t (cntsat) << 32 );
93
+ doc_parser.doc .tape [start_loc ] |= doc_parser.current_loc | (uint64_t (cntsat) << 32 );
98
94
}
99
95
100
- really_inline void end_object () {
96
+ really_inline void end_object (uint32_t start_loc, uint32_t count ) {
101
97
log_end_value (" object" );
102
- end_scope (internal::tape_type::END_OBJECT);
98
+ end_scope (internal::tape_type::END_OBJECT, start_loc, count );
103
99
}
104
- really_inline void end_array () {
100
+ really_inline void end_array (uint32_t start_loc, uint32_t count ) {
105
101
log_end_value (" array" );
106
- end_scope (internal::tape_type::END_ARRAY);
102
+ end_scope (internal::tape_type::END_ARRAY, start_loc, count );
107
103
}
108
- really_inline void end_document () {
104
+ really_inline void end_document (uint32_t start_loc, uint32_t count ) {
109
105
log_end_value (" document" );
110
- end_scope (internal::tape_type::ROOT);
106
+ end_scope (internal::tape_type::ROOT, start_loc, count );
111
107
}
112
108
113
109
really_inline void write_tape (uint64_t val, internal::tape_type t) noexcept {
114
110
doc_parser.doc .tape [doc_parser.current_loc ++] = val | ((uint64_t (char (t))) << 56 );
115
111
}
116
112
117
- // increment_count increments the count of keys in an object or values in an array.
118
- // Note that if you are at the level of the values or elements, the count
119
- // must be increment in the preceding depth (depth-1) where the array or
120
- // the object resides.
121
- really_inline void increment_count () {
122
- doc_parser.containing_scope [depth].count ++; // we have a key value pair in the object at parser.depth - 1
123
- }
124
-
125
113
really_inline uint8_t *on_start_string () noexcept {
126
114
// we advance the point, accounting for the fact that we have a NULL termination
127
115
write_tape (current_string_buf_loc - doc_parser.doc .string_buf .get (), internal::tape_type::STRING);
@@ -279,38 +267,41 @@ struct structural_parser {
279
267
}
280
268
281
269
WARN_UNUSED really_inline bool parse_object_inline () {
270
+ uint32_t start_loc = doc_parser.current_loc ;
282
271
if (start_object ()) { return true ; }
283
272
switch (advance_char ()) {
284
273
case ' "' :
285
- increment_count ();
286
- // Key
287
- if (parse_string (true )) { return true ; }
288
- while (true ) {
289
-
290
- // :
291
- if (advance_char () != ' :' ) { log_error (" Missing colon after key in object" ); return true ; }
292
-
293
- // Value
294
- advance_char ();
295
- if (parse_value ()) { return true ; }
296
-
297
- switch (advance_char ()) {
298
- case ' ,' :
299
- increment_count ();
300
- if (advance_char () != ' "' ) { log_error (" Key string missing at beginning of field in object" ); return true ; }
301
- if (parse_string (true )) { return true ; }
302
- continue ;
303
- case ' }' :
304
- end_object ();
305
- return false ;
306
- default :
307
- log_error (" No comma between object fields" );
308
- return true ;
274
+ {
275
+ uint32_t count = 1 ;
276
+ // Key
277
+ if (parse_string (true )) { return true ; }
278
+ while (true ) {
279
+
280
+ // :
281
+ if (advance_char () != ' :' ) { log_error (" Missing colon after key in object" ); return true ; }
282
+
283
+ // Value
284
+ advance_char ();
285
+ if (parse_value ()) { return true ; }
286
+
287
+ switch (advance_char ()) {
288
+ case ' ,' :
289
+ count++;
290
+ if (advance_char () != ' "' ) { log_error (" Key string missing at beginning of field in object" ); return true ; }
291
+ if (parse_string (true )) { return true ; }
292
+ continue ;
293
+ case ' }' :
294
+ end_object (start_loc, count);
295
+ return false ;
296
+ default :
297
+ log_error (" No comma between object fields" );
298
+ return true ;
299
+ }
309
300
}
310
301
}
311
302
break ;
312
303
case ' }' :
313
- end_object ();
304
+ end_object (start_loc, 0 );
314
305
return false ;
315
306
default :
316
307
log_error (" Object does not start with a key" );
@@ -336,24 +327,25 @@ struct structural_parser {
336
327
}
337
328
338
329
WARN_UNUSED really_inline bool parse_array_inline () {
330
+ uint32_t start_loc = doc_parser.current_loc ;
339
331
if (start_array ()) { return true ; }
340
332
341
333
if (advance_char () == ' ]' ) {
342
- end_array ();
334
+ end_array (start_loc, 0 );
343
335
return false ;
344
336
}
345
- increment_count ();
346
337
338
+ uint32_t count = 1 ;
347
339
while (true ) {
348
340
if (parse_value ()) { return true ; }
349
341
350
342
switch (advance_char ()) {
351
343
case ' ,' :
352
- increment_count () ;
344
+ count++ ;
353
345
advance_char ();
354
346
continue ;
355
347
case ' ]' :
356
- end_array ();
348
+ end_array (start_loc, count );
357
349
return false ;
358
350
default :
359
351
log_error (" Missing comma between array values" );
@@ -368,15 +360,11 @@ struct structural_parser {
368
360
log_error (" More than one JSON value at the root of the document, or extra characters at the end of the JSON!" );
369
361
return on_error (TAPE_ERROR);
370
362
}
371
- end_document ();
363
+ end_document (0 , 1 );
372
364
if (depth != 0 ) {
373
365
log_error (" Unclosed objects or arrays!" );
374
366
return on_error (TAPE_ERROR);
375
367
}
376
- if (doc_parser.containing_scope [depth].tape_index != 0 ) {
377
- log_error (" IMPOSSIBLE: root scope tape index did not start at 0!" );
378
- return on_error (TAPE_ERROR);
379
- }
380
368
381
369
return on_success (SUCCESS);
382
370
}
0 commit comments