From b7cacf13f4f34c82c01348dbd78e2669ee0e77d4 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 19 May 2025 12:37:06 -0400 Subject: [PATCH] Call on_number_data with all available bytes --- src/parser3.h | 75 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/src/parser3.h b/src/parser3.h index 7b4e9e9..980d1a9 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -68,6 +68,7 @@ enum Symbol : uint8_t { T_DIGIT, T_ONENINE, T_EOF, + T_END_NUMBER, N_SYMBOL_COUNT, // Must be last }; struct Parser3 { @@ -78,11 +79,16 @@ struct Parser3 { [[nodiscard]] Status parse(char *buf, int len) { complete = len == 0; - this->buf = buf; + this->buf = this->dataBegin = buf; this->bufEnd = buf + len; return keepGoing(this); } + void flushNumber() { + int len = buf - dataBegin; + callbacks->on_number_data(data, dataBegin, len); + } + [[nodiscard]] bool empty() const { return stackPtr == stack; } void pop() { assert(!empty()); @@ -114,6 +120,8 @@ struct Parser3 { [[maybe_unused]] void debugPrint(); char *buf = nullptr; char *bufEnd = nullptr; + // Used for flushing pending data with on_*_data callbacks + char *dataBegin; const Callbacks *const callbacks; void *const data; Symbol stack[kMaxStackSize]; @@ -520,7 +528,7 @@ inline Status t_hex(Parser3 *self) { inline Status n_number(Parser3 *self) { self->pop(); - if (auto s = self->push({N_INTEGER, N_FRACTION, N_EXPONENT})) { + if (auto s = self->push({N_INTEGER, N_FRACTION, N_EXPONENT, T_END_NUMBER})) { return s; } MUSTTAIL return Parser3::keepGoing(self); @@ -531,9 +539,9 @@ inline Status n_integer(Parser3 *self) { return S_REJECT; } self->callbacks->on_begin_number(self->data); + self->dataBegin = self->buf; switch (*self->buf) { case '0': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); MUSTTAIL return Parser3::keepGoing(self); @@ -546,7 +554,6 @@ inline Status n_integer(Parser3 *self) { case '7': case '8': case '9': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_DIGITS2})) { @@ -554,7 +561,6 @@ inline Status n_integer(Parser3 *self) { } MUSTTAIL return Parser3::keepGoing(self); case '-': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_INTEGER2})) { @@ -572,7 +578,6 @@ inline Status n_integer2(Parser3 *self) { } switch (*self->buf) { case '0': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); MUSTTAIL return Parser3::keepGoing(self); @@ -585,7 +590,6 @@ inline Status n_integer2(Parser3 *self) { case '7': case '8': case '9': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_DIGITS2})) { @@ -612,7 +616,6 @@ inline Status n_digits(Parser3 *self) { case '7': case '8': case '9': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_DIGITS2})) { @@ -640,7 +643,6 @@ inline Status n_digits2(Parser3 *self) { case '7': case '8': case '9': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; MUSTTAIL return Parser3::keepGoing(self); default: @@ -656,7 +658,6 @@ inline Status n_fraction(Parser3 *self) { } switch (*self->buf) { case '.': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_DIGITS})) { @@ -677,7 +678,6 @@ inline Status n_exponent(Parser3 *self) { switch (*self->buf) { case 'e': case 'E': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); if (auto s = self->push({N_SIGN, N_DIGITS})) { @@ -698,7 +698,6 @@ inline Status n_sign(Parser3 *self) { switch (*self->buf) { case '+': case '-': - self->callbacks->on_number_data(self->data, self->buf, 1); ++self->buf; self->pop(); MUSTTAIL return Parser3::keepGoing(self); @@ -779,6 +778,13 @@ inline Status t_eof(Parser3 *self) { return self->complete ? S_OK : S_AGAIN; } +inline Status t_end_number(Parser3 *self) { + self->pop(); + self->flushNumber(); + self->callbacks->on_end_number(self->data); + MUSTTAIL return Parser3::keepGoing(self); +} + constexpr inline struct ContinuationTable { constexpr ContinuationTable() { // Defaults @@ -825,6 +831,7 @@ constexpr inline struct ContinuationTable { continuations[T_DIGIT] = t_digit; continuations[T_ONENINE] = t_onenine; continuations[T_EOF] = t_eof; + continuations[T_END_NUMBER] = t_end_number; symbolNames[N_JSON] = "n_json"; symbolNames[N_VALUE] = "n_value"; symbolNames[N_OBJECT] = "n_object"; @@ -860,6 +867,7 @@ constexpr inline struct ContinuationTable { symbolNames[T_DIGIT] = "t_digit"; symbolNames[T_ONENINE] = "t_onenine"; symbolNames[T_EOF] = "t_eof"; + symbolNames[T_END_NUMBER] = "t_end_number"; } Continuation continuations[N_SYMBOL_COUNT]{}; const char *symbolNames[N_SYMBOL_COUNT]{}; @@ -867,6 +875,49 @@ constexpr inline struct ContinuationTable { inline Status Parser3::keepGoing(Parser3 *self) { if (self->len() == 0 && !self->complete) { + switch (self->top()) { + case N_NUMBER: + case N_INTEGER: + case N_INTEGER2: + case N_DIGITS: + case N_DIGITS2: + case N_FRACTION: + case N_EXPONENT: + case N_SIGN: + case T_DIGIT: + case T_ONENINE: + case T_END_NUMBER: + self->flushNumber(); + break; + case N_JSON: + case N_VALUE: + case N_OBJECT: + case N_OBJECT2: + case N_OBJECT3: + case N_ARRAY: + case N_ARRAY2: + case N_ARRAY3: + case N_ELEMENT: + case N_STRING: + case N_STRING2: + case N_STRING_FOLLOWING_ESCAPE: + case N_WHITESPACE: + case N_TRUE: + case N_FALSE: + case N_NULL: + case T_R: + case T_U: + case T_A: + case T_L: + case T_S: + case T_COLON: + case T_UTF8_CONTINUATION_BYTE: + case T_UTF8_LAST_CONTINUATION_BYTE: + case T_HEX: + case T_EOF: + case N_SYMBOL_COUNT: + break; + } return S_AGAIN; } // self->debugPrint();