From 5df9d958abe7dc96e849e201fd4f121657eba932 Mon Sep 17 00:00:00 2001 From: Andrew Noyes Date: Mon, 23 Jun 2025 14:00:29 -0400 Subject: [PATCH] Unroll whitespace-skipping loop --- src/parser3.h | 77 ++++++++++++++++++++++++--------------------------- 1 file changed, 36 insertions(+), 41 deletions(-) diff --git a/src/parser3.h b/src/parser3.h index c8636cd..412b4ce 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -750,17 +750,33 @@ struct Parser3 { Utf8Dfa strDfa; }; +inline PRESERVE_NONE WeaselJsonStatus skipWhitespace(char *&buf, char *bufEnd) { + constexpr int kStride = 4; + for (;;) { + if (bufEnd - buf < kStride) [[unlikely]] { + while (buf != bufEnd && tables.whitespace[uint8_t(*buf)]) { + ++buf; + } + return buf == bufEnd ? WeaselJson_AGAIN : WeaselJson_OK; + } + for (int i = 0; i < kStride; ++i) { + if (tables.whitespace[uint8_t(*buf)]) { + ++buf; + } else { + return WeaselJson_OK; + } + } + } +} + inline PRESERVE_NONE WeaselJsonStatus n_whitespace(Parser3 *self, char *buf, char *bufEnd) { - if (bufEnd - buf == 0) { + if (buf == bufEnd) { self->pop(); MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd); } - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } self->pop(); MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd); @@ -856,11 +872,8 @@ inline PRESERVE_NONE WeaselJsonStatus scan_string(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } switch (*buf) { case '{': @@ -963,11 +976,8 @@ inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_object2(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } switch (*buf) { case '}': @@ -992,11 +1002,8 @@ inline PRESERVE_NONE WeaselJsonStatus n_object2(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_object3(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } switch (*buf) { case '}': @@ -1019,11 +1026,8 @@ inline PRESERVE_NONE WeaselJsonStatus n_object3(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_array2(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } switch (*buf) { case ']': @@ -1043,11 +1047,8 @@ inline PRESERVE_NONE WeaselJsonStatus n_array2(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_array3(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } switch (*buf) { case ']': @@ -1070,11 +1071,8 @@ inline PRESERVE_NONE WeaselJsonStatus n_array3(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_string(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } if (*buf != '"') [[unlikely]] { return WeaselJson_REJECT; @@ -1318,11 +1316,8 @@ inline PRESERVE_NONE WeaselJsonStatus singleChar(Parser3 *self, char *buf, char *bufEnd) { if constexpr (kSkipWhitespace) { assert(bufEnd - buf != 0); - while (tables.whitespace[uint8_t(*buf)]) { - ++buf; - if (buf == bufEnd) { - return WeaselJson_AGAIN; - } + if (auto s = skipWhitespace(buf, bufEnd)) { + return s; } } if (*buf == kChar) {