From 0c7cb7950a4be0f0ee6cbf362b4b07561a238110 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 16 Jan 2025 13:27:13 +0100 Subject: [PATCH] Use a lookup table for whitespaces and comments --- ext/json/ext/parser/parser.c | 83 +++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/ext/json/ext/parser/parser.c b/ext/json/ext/parser/parser.c index e505ed8e..eb73e19f 100644 --- a/ext/json/ext/parser/parser.c +++ b/ext/json/ext/parser/parser.c @@ -442,58 +442,63 @@ static void raise_parse_error(const char *format, const char *start) rb_enc_raise(enc_utf8, rb_path2class("JSON::ParserError"), format, ptr); } -static inline void -json_eat_whitespace(JSON_ParserState *state) { - while (state->cursor < state->end) { - switch (*state->cursor) { - case ' ': - case '\t': - case '\n': - case '\r': - state->cursor++; - break; +static const bool whitespace[256] = { + [' '] = 1, + ['\t'] = 1, + ['\n'] = 1, + ['\r'] = 1, + ['/'] = 1, +}; + +static void +json_eat_comments(JSON_ParserState *state) +{ + if (state->cursor + 1 < state->end) { + switch(state->cursor[1]) { case '/': { - if (state->cursor + 1 < state->end) { - switch(state->cursor[1]) { - case '/': { - state->cursor = memchr(state->cursor, '\n', state->end - state->cursor); - if (!state->cursor) { - state->cursor = state->end; - } else { - state->cursor++; - } - break; - } - case '*': { - state->cursor += 2; - while (true) { - state->cursor = memchr(state->cursor, '*', state->end - state->cursor); - if (!state->cursor) { - state->cursor = state->end; - break; - } else { - state->cursor++; - if (state->cursor < state->end && *state->cursor == '/') { - state->cursor++; - break; - } - } - } + state->cursor = memchr(state->cursor, '\n', state->end - state->cursor); + if (!state->cursor) { + state->cursor = state->end; + } else { + state->cursor++; + } + break; + } + case '*': { + state->cursor += 2; + while (true) { + state->cursor = memchr(state->cursor, '*', state->end - state->cursor); + if (!state->cursor) { + state->cursor = state->end; + break; + } else { + state->cursor++; + if (state->cursor < state->end && *state->cursor == '/') { + state->cursor++; break; } - default: - return; } } break; } - default: return; } } } +static inline void +json_eat_whitespace(JSON_ParserState *state) +{ + while (state->cursor < state->end && RB_UNLIKELY(whitespace[(unsigned char)*state->cursor])) { + if (RB_LIKELY(*state->cursor != '/')) { + state->cursor++; + } else { + json_eat_comments(state); + } + } +} + static inline VALUE build_string(const char *start, const char *end, bool intern, bool symbolize) { if (symbolize) {