Skip to content

Commit 81c86d7

Browse files
committed
Structural iterator
1 parent d9a9fd3 commit 81c86d7

File tree

4 files changed

+117
-97
lines changed

4 files changed

+117
-97
lines changed

src/generic/numberparsing.h

Lines changed: 31 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,8 @@ really_inline double subnormal_power10(double base, int64_t negative_exponent) {
145145
//
146146
// Note: a redesign could avoid this function entirely.
147147
//
148-
never_inline bool parse_float(const uint8_t *const buf, document::parser &parser,
149-
const uint32_t offset, bool found_minus) {
150-
const char *p = reinterpret_cast<const char *>(buf + offset);
148+
never_inline bool parse_float(const uint8_t *const src, document::parser &parser, bool found_minus) {
149+
const char *p = reinterpret_cast<const char *>(src);
151150
bool negative = false;
152151
if (found_minus) {
153152
++p;
@@ -179,7 +178,7 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
179178
: 0);
180179
} else {
181180
#ifdef JSON_TEST_NUMBERS // for unit testing
182-
found_invalid_number(buf + offset);
181+
found_invalid_number(src);
183182
#endif
184183
return false;
185184
}
@@ -202,7 +201,7 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
202201
}
203202
if (!is_integer(*p)) {
204203
#ifdef JSON_TEST_NUMBERS // for unit testing
205-
found_invalid_number(buf + offset);
204+
found_invalid_number(src);
206205
#endif
207206
return false;
208207
}
@@ -228,7 +227,7 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
228227
if (exp_number > 0x100000000) { // we need to check for overflows
229228
// we refuse to parse this
230229
#ifdef JSON_TEST_NUMBERS // for unit testing
231-
found_invalid_number(buf + offset);
230+
found_invalid_number(src);
232231
#endif
233232
return false;
234233
}
@@ -246,7 +245,7 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
246245
// We know for sure that we have a number that is too large,
247246
// we refuse to parse this
248247
#ifdef JSON_TEST_NUMBERS // for unit testing
249-
found_invalid_number(buf + offset);
248+
found_invalid_number(src);
250249
#endif
251250
return false;
252251
}
@@ -264,14 +263,14 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
264263
// check that we can go from long double to double safely.
265264
if(i > std::numeric_limits<double>::max()) {
266265
#ifdef JSON_TEST_NUMBERS // for unit testing
267-
found_invalid_number(buf + offset);
266+
found_invalid_number(src);
268267
#endif
269268
return false;
270269
}
271270
double d = negative ? -i : i;
272271
parser.on_number_double(d);
273272
#ifdef JSON_TEST_NUMBERS // for unit testing
274-
found_float(d, buf + offset);
273+
found_float(d, src);
275274
#endif
276275
return is_structural_or_whitespace(*p);
277276
}
@@ -284,11 +283,8 @@ never_inline bool parse_float(const uint8_t *const buf, document::parser &parser
284283
//
285284
// This function will almost never be called!!!
286285
//
287-
never_inline bool parse_large_integer(const uint8_t *const buf,
288-
document::parser &parser,
289-
const uint32_t offset,
290-
bool found_minus) {
291-
const char *p = reinterpret_cast<const char *>(buf + offset);
286+
never_inline bool parse_large_integer(const uint8_t *const src, document::parser &parser, bool found_minus) {
287+
const char *p = reinterpret_cast<const char *>(src);
292288

293289
bool negative = false;
294290
if (found_minus) {
@@ -309,13 +305,13 @@ never_inline bool parse_large_integer(const uint8_t *const buf,
309305
digit = *p - '0';
310306
if (mul_overflow(i, 10, &i)) {
311307
#ifdef JSON_TEST_NUMBERS // for unit testing
312-
found_invalid_number(buf + offset);
308+
found_invalid_number(src);
313309
#endif
314310
return false; // overflow
315311
}
316312
if (add_overflow(i, digit, &i)) {
317313
#ifdef JSON_TEST_NUMBERS // for unit testing
318-
found_invalid_number(buf + offset);
314+
found_invalid_number(src);
319315
#endif
320316
return false; // overflow
321317
}
@@ -326,7 +322,7 @@ never_inline bool parse_large_integer(const uint8_t *const buf,
326322
if (i > 0x8000000000000000) {
327323
// overflows!
328324
#ifdef JSON_TEST_NUMBERS // for unit testing
329-
found_invalid_number(buf + offset);
325+
found_invalid_number(src);
330326
#endif
331327
return false; // overflow
332328
} else if (i == 0x8000000000000000) {
@@ -336,14 +332,14 @@ never_inline bool parse_large_integer(const uint8_t *const buf,
336332
constexpr int64_t signed_answer = INT64_MIN;
337333
parser.on_number_s64(signed_answer);
338334
#ifdef JSON_TEST_NUMBERS // for unit testing
339-
found_integer(signed_answer, buf + offset);
335+
found_integer(signed_answer, src);
340336
#endif
341337
} else {
342338
// we can negate safely
343339
int64_t signed_answer = -static_cast<int64_t>(i);
344340
parser.on_number_s64(signed_answer);
345341
#ifdef JSON_TEST_NUMBERS // for unit testing
346-
found_integer(signed_answer, buf + offset);
342+
found_integer(signed_answer, src);
347343
#endif
348344
}
349345
} else {
@@ -352,20 +348,20 @@ never_inline bool parse_large_integer(const uint8_t *const buf,
352348
// fallback on unsigned integers if absolutely necessary.
353349
if(i < 0x8000000000000000) {
354350
#ifdef JSON_TEST_NUMBERS // for unit testing
355-
found_integer(i, buf + offset);
351+
found_integer(i, src);
356352
#endif
357353
parser.on_number_s64(i);
358354
} else {
359355
#ifdef JSON_TEST_NUMBERS // for unit testing
360-
found_unsigned_integer(i, buf + offset);
356+
found_unsigned_integer(i, src);
361357
#endif
362358
parser.on_number_u64(i);
363359
}
364360
}
365361
return is_structural_or_whitespace(*p);
366362
}
367363

368-
// parse the number at buf + offset
364+
// parse the number at src
369365
// define JSON_TEST_NUMBERS for unit testing
370366
//
371367
// It is assumed that the number is followed by a structural ({,},],[) character
@@ -374,23 +370,22 @@ never_inline bool parse_large_integer(const uint8_t *const buf,
374370
// content and append a space before calling this function.
375371
//
376372
// Our objective is accurate parsing (ULP of 0 or 1) at high speed.
377-
really_inline bool parse_number(UNUSED const uint8_t *const buf,
378-
UNUSED const uint32_t offset,
373+
really_inline bool parse_number(UNUSED const uint8_t *const src,
379374
UNUSED bool found_minus,
380375
document::parser &parser) {
381376
#ifdef SIMDJSON_SKIPNUMBERPARSING // for performance analysis, it is sometimes
382377
// useful to skip parsing
383378
parser.on_number_s64(0); // always write zero
384379
return true; // always succeeds
385380
#else
386-
const char *p = reinterpret_cast<const char *>(buf + offset);
381+
const char *p = reinterpret_cast<const char *>(src);
387382
bool negative = false;
388383
if (found_minus) {
389384
++p;
390385
negative = true;
391386
if (!is_integer(*p)) { // a negative sign must be followed by an integer
392387
#ifdef JSON_TEST_NUMBERS // for unit testing
393-
found_invalid_number(buf + offset);
388+
found_invalid_number(src);
394389
#endif
395390
return false;
396391
}
@@ -402,15 +397,15 @@ really_inline bool parse_number(UNUSED const uint8_t *const buf,
402397
++p;
403398
if (is_not_structural_or_whitespace_or_exponent_or_decimal(*p)) {
404399
#ifdef JSON_TEST_NUMBERS // for unit testing
405-
found_invalid_number(buf + offset);
400+
found_invalid_number(src);
406401
#endif
407402
return false;
408403
}
409404
i = 0;
410405
} else {
411406
if (!(is_integer(*p))) { // must start with an integer
412407
#ifdef JSON_TEST_NUMBERS // for unit testing
413-
found_invalid_number(buf + offset);
408+
found_invalid_number(src);
414409
#endif
415410
return false;
416411
}
@@ -445,7 +440,7 @@ really_inline bool parse_number(UNUSED const uint8_t *const buf,
445440
// we will handle the overflow later
446441
} else {
447442
#ifdef JSON_TEST_NUMBERS // for unit testing
448-
found_invalid_number(buf + offset);
443+
found_invalid_number(src);
449444
#endif
450445
return false;
451446
}
@@ -480,7 +475,7 @@ really_inline bool parse_number(UNUSED const uint8_t *const buf,
480475
}
481476
if (!is_integer(*p)) {
482477
#ifdef JSON_TEST_NUMBERS // for unit testing
483-
found_invalid_number(buf + offset);
478+
found_invalid_number(src);
484479
#endif
485480
return false;
486481
}
@@ -501,7 +496,7 @@ really_inline bool parse_number(UNUSED const uint8_t *const buf,
501496
if (exp_number > 0x100000000) { // we need to check for overflows
502497
// we refuse to parse this
503498
#ifdef JSON_TEST_NUMBERS // for unit testing
504-
found_invalid_number(buf + offset);
499+
found_invalid_number(src);
505500
#endif
506501
return false;
507502
}
@@ -526,31 +521,31 @@ really_inline bool parse_number(UNUSED const uint8_t *const buf,
526521
// Ok, chances are good that we had an overflow!
527522
// this is almost never going to get called!!!
528523
// we start anew, going slowly!!!
529-
return parse_float(buf, parser, offset, found_minus);
524+
return parse_float(src, parser, found_minus);
530525
}
531526
}
532527
if (unlikely((power_index > 2 * 308))) { // this is uncommon!!!
533528
// this is almost never going to get called!!!
534529
// we start anew, going slowly!!!
535-
return parse_float(buf, parser, offset, found_minus);
530+
return parse_float(src, parser, found_minus);
536531
}
537532
double factor = power_of_ten[power_index];
538533
factor = negative ? -factor : factor;
539534
double d = i * factor;
540535
parser.on_number_double(d);
541536
#ifdef JSON_TEST_NUMBERS // for unit testing
542-
found_float(d, buf + offset);
537+
found_float(d, src);
543538
#endif
544539
} else {
545540
if (unlikely(digit_count >= 18)) { // this is uncommon!!!
546541
// there is a good chance that we had an overflow, so we need
547542
// need to recover: we parse the whole thing again.
548-
return parse_large_integer(buf, parser, offset, found_minus);
543+
return parse_large_integer(src, parser, found_minus);
549544
}
550545
i = negative ? 0 - i : i;
551546
parser.on_number_s64(i);
552547
#ifdef JSON_TEST_NUMBERS // for unit testing
553-
found_integer(i, buf + offset);
548+
found_integer(i, src);
554549
#endif
555550
}
556551
return is_structural_or_whitespace(*p);

0 commit comments

Comments
 (0)