Skip to content

Commit 9475b94

Browse files
committed
Return error codes from parse_number
1 parent 18564f1 commit 9475b94

File tree

2 files changed

+29
-28
lines changed

2 files changed

+29
-28
lines changed

src/generic/stage2/numberparsing.h

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ namespace stage2 {
77
namespace numberparsing {
88

99
#ifdef JSON_TEST_NUMBERS
10-
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), false)
10+
#define INVALID_NUMBER(SRC) (found_invalid_number((SRC)), NUMBER_ERROR)
1111
#define WRITE_INTEGER(VALUE, SRC, WRITER) (found_integer((VALUE), (SRC)), writer.append_s64((VALUE)))
1212
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) (found_unsigned_integer((VALUE), (SRC)), writer.append_u64((VALUE)))
1313
#define WRITE_DOUBLE(VALUE, SRC, WRITER) (found_float((VALUE), (SRC)), writer.append_double((VALUE)))
1414
#else
15-
#define INVALID_NUMBER(SRC) (false)
15+
#define INVALID_NUMBER(SRC) (NUMBER_ERROR)
1616
#define WRITE_INTEGER(VALUE, SRC, WRITER) writer.append_s64((VALUE))
1717
#define WRITE_UNSIGNED(VALUE, SRC, WRITER) writer.append_u64((VALUE))
1818
#define WRITE_DOUBLE(VALUE, SRC, WRITER) writer.append_double((VALUE))
@@ -252,11 +252,11 @@ simdjson_really_inline bool is_made_of_eight_digits_fast(const uint8_t *chars) {
252252
}
253253

254254
template<typename W>
255-
bool slow_float_parsing(SIMDJSON_UNUSED const uint8_t * src, W writer) {
255+
error_code slow_float_parsing(SIMDJSON_UNUSED const uint8_t * src, W writer) {
256256
double d;
257257
if (parse_float_strtod(src, &d)) {
258258
WRITE_DOUBLE(d, src, writer);
259-
return true;
259+
return SUCCESS;
260260
}
261261
return INVALID_NUMBER(src);
262262
}
@@ -273,7 +273,7 @@ simdjson_really_inline bool parse_digit(const uint8_t c, I &i) {
273273
return true;
274274
}
275275

276-
simdjson_really_inline bool parse_decimal(SIMDJSON_UNUSED const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
276+
simdjson_really_inline error_code parse_decimal(SIMDJSON_UNUSED const uint8_t *const src, const uint8_t *&p, uint64_t &i, int64_t &exponent) {
277277
// we continue with the fiction that we have an integer. If the
278278
// floating point number is representable as x * 10^z for some integer
279279
// z that fits in 53 bits, then we will be able to convert back the
@@ -296,10 +296,10 @@ simdjson_really_inline bool parse_decimal(SIMDJSON_UNUSED const uint8_t *const s
296296
if (exponent == 0) {
297297
return INVALID_NUMBER(src);
298298
}
299-
return true;
299+
return SUCCESS;
300300
}
301301

302-
simdjson_really_inline bool parse_exponent(SIMDJSON_UNUSED const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
302+
simdjson_really_inline error_code parse_exponent(SIMDJSON_UNUSED const uint8_t *const src, const uint8_t *&p, int64_t &exponent) {
303303
// Exp Sign: -123.456e[-]78
304304
bool neg_exp = ('-' == *p);
305305
if (neg_exp || '+' == *p) { p++; } // Skip + as well
@@ -347,11 +347,11 @@ simdjson_really_inline bool parse_exponent(SIMDJSON_UNUSED const uint8_t *const
347347
// is bounded in magnitude by the size of the JSON input, we are fine in this universe.
348348
// To sum it up: the next line should never overflow.
349349
exponent += (neg_exp ? -exp_number : exp_number);
350-
return true;
350+
return SUCCESS;
351351
}
352352

353353
template<typename W>
354-
simdjson_really_inline bool write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, int digit_count, int64_t exponent, W &writer) {
354+
simdjson_really_inline error_code write_float(const uint8_t *const src, bool negative, uint64_t i, const uint8_t * start_digits, int digit_count, int64_t exponent, W &writer) {
355355
// If we frequently had to deal with long strings of digits,
356356
// we could extend our code by using a 128-bit integer instead
357357
// of a 64-bit integer. However, this is uncommon in practice.
@@ -373,11 +373,11 @@ simdjson_really_inline bool write_float(const uint8_t *const src, bool negative,
373373
// 10000000000000000000000000000000000000000000e+308
374374
// 3.1415926535897932384626433832795028841971693993751
375375
//
376-
bool success = slow_float_parsing(src, writer);
376+
error_code error = slow_float_parsing(src, writer);
377377
// The number was already written, but we made a copy of the writer
378378
// when we passed it to the parse_large_integer() function, so
379379
writer.skip_double();
380-
return success;
380+
return error;
381381
}
382382
}
383383
// NOTE: it's weird that the simdjson_unlikely() only wraps half the if, but it seems to get slower any other
@@ -386,11 +386,11 @@ simdjson_really_inline bool write_float(const uint8_t *const src, bool negative,
386386
if (simdjson_unlikely(exponent < FASTFLOAT_SMALLEST_POWER) || (exponent > FASTFLOAT_LARGEST_POWER)) {
387387
// this is almost never going to get called!!!
388388
// we start anew, going slowly!!!
389-
bool success = slow_float_parsing(src, writer);
389+
error_code error = slow_float_parsing(src, writer);
390390
// The number was already written, but we made a copy of the writer when we passed it to the
391391
// slow_float_parsing() function, so we have to skip those tape spots now that we've returned
392392
writer.skip_double();
393-
return success;
393+
return error;
394394
}
395395
bool success = true;
396396
double d = compute_float_64(exponent, i, negative, &success);
@@ -399,16 +399,16 @@ simdjson_really_inline bool write_float(const uint8_t *const src, bool negative,
399399
if (!parse_float_strtod(src, &d)) { return INVALID_NUMBER(src); }
400400
}
401401
WRITE_DOUBLE(d, src, writer);
402-
return true;
402+
return SUCCESS;
403403
}
404404

405405
// for performance analysis, it is sometimes useful to skip parsing
406406
#ifdef SIMDJSON_SKIPNUMBERPARSING
407407

408408
template<typename W>
409-
simdjson_really_inline bool parse_number(const uint8_t *const, W &writer) {
409+
simdjson_really_inline error_code parse_number(const uint8_t *const, W &writer) {
410410
writer.append_s64(0); // always write zero
411-
return true; // always succeeds
411+
return SUCCESS; // always succeeds
412412
}
413413

414414
#else
@@ -423,7 +423,7 @@ simdjson_really_inline bool parse_number(const uint8_t *const, W &writer) {
423423
//
424424
// Our objective is accurate parsing (ULP of 0) at high speed.
425425
template<typename W>
426-
simdjson_really_inline bool parse_number(const uint8_t *const src, W &writer) {
426+
simdjson_really_inline error_code parse_number(const uint8_t *const src, W &writer) {
427427

428428
//
429429
// Check for minus sign
@@ -451,17 +451,19 @@ simdjson_really_inline bool parse_number(const uint8_t *const src, W &writer) {
451451
if ('.' == *p) {
452452
is_float = true;
453453
++p;
454-
if (!parse_decimal(src, p, i, exponent)) { return false; }
454+
SIMDJSON_TRY( parse_decimal(src, p, i, exponent) );
455455
digit_count = int(p - start_digits); // used later to guard against overflows
456456
}
457457
if (('e' == *p) || ('E' == *p)) {
458458
is_float = true;
459459
++p;
460-
if (!parse_exponent(src, p, exponent)) { return false; }
460+
SIMDJSON_TRY( parse_exponent(src, p, exponent) );
461461
}
462462
if (is_float) {
463463
const bool clean_end = is_structural_or_whitespace(*p);
464-
return write_float(src, negative, i, start_digits, digit_count, exponent, writer) && clean_end;
464+
SIMDJSON_TRY( write_float(src, negative, i, start_digits, digit_count, exponent, writer) );
465+
if (!clean_end) { return INVALID_NUMBER(src); }
466+
return SUCCESS;
465467
}
466468

467469
// The longest negative 64-bit number is 19 digits.
@@ -470,13 +472,12 @@ simdjson_really_inline bool parse_number(const uint8_t *const src, W &writer) {
470472
int longest_digit_count = negative ? 19 : 20;
471473
if (digit_count > longest_digit_count) { return INVALID_NUMBER(src); }
472474
if (digit_count == longest_digit_count) {
473-
if(negative) {
475+
if (negative) {
474476
// Anything negative above INT64_MAX+1 is invalid
475-
if (i > uint64_t(INT64_MAX)+1) {
476-
return INVALID_NUMBER(src);
477-
}
477+
if (i > uint64_t(INT64_MAX)+1) { return INVALID_NUMBER(src); }
478478
WRITE_INTEGER(~i+1, src, writer);
479-
return is_structural_or_whitespace(*p);
479+
if (!is_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
480+
return SUCCESS;
480481
// Positive overflow check:
481482
// - A 20 digit number starting with 2-9 is overflow, because 18,446,744,073,709,551,615 is the
482483
// biggest uint64_t.
@@ -498,7 +499,8 @@ simdjson_really_inline bool parse_number(const uint8_t *const src, W &writer) {
498499
} else {
499500
WRITE_INTEGER(negative ? (~i+1) : i, src, writer);
500501
}
501-
return is_structural_or_whitespace(*p);
502+
if (!is_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); }
503+
return SUCCESS;
502504
}
503505

504506
// SAX functions

src/generic/stage2/tape_builder.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,7 @@ SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_
160160

161161
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_number(json_iterator &iter, const uint8_t *value) noexcept {
162162
iter.log_value("number");
163-
if (!numberparsing::parse_number(value, tape)) { iter.log_error("Invalid number"); return NUMBER_ERROR; }
164-
return SUCCESS;
163+
return numberparsing::parse_number(value, tape);
165164
}
166165

167166
SIMDJSON_WARN_UNUSED simdjson_really_inline error_code tape_builder::visit_root_number(json_iterator &iter, const uint8_t *value) noexcept {

0 commit comments

Comments
 (0)