diff --git a/src/parser3.h b/src/parser3.h index bc0482f..7da709e 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -780,6 +780,31 @@ inline PRESERVE_NONE WeaselJsonStatus n_number(Parser3 *self, char *buf, MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd); } +// Advance buf until double quote, backslash, invalid utf8, or codepoint < +// 0x20 +inline PRESERVE_NONE WeaselJsonStatus n_scan_string(Parser3 *self, char *&buf, + char *bufEnd) { + const auto before = buf; + + buf = (char *)self->strDfa.scan(buf, bufEnd); + + int len = buf - before; + if (self->writeBuf != before) { + memmove(self->writeBuf, before, len); + } + self->writeBuf += len; + + if (buf == bufEnd) { + self->flushString(false); + return WeaselJson_AGAIN; + } + + if (!self->strDfa.accept()) [[unlikely]] { + return WeaselJson_REJECT; + } + return WeaselJson_OK; +} + inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, char *bufEnd) { assert(bufEnd - buf != 0); @@ -811,10 +836,30 @@ inline PRESERVE_NONE WeaselJsonStatus n_value(Parser3 *self, char *buf, self->dataBegin = self->writeBuf = buf; self->pop(); self->strDfa.reset(); - if (auto s = self->push({N_STRING2})) { + if (auto s = n_scan_string(self, buf, bufEnd)) { + if (s == WeaselJson_AGAIN) { + if (auto s2 = self->push({N_STRING2})) { + return s2; + } + } return s; } - break; + { + switch (*buf) { + case '"': + self->flushString(true); + ++buf; + MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd); + case '\\': + ++buf; + if (auto s = self->push({N_STRING_FOLLOWING_ESCAPE})) { + return s; + } + MUSTTAIL return Parser3::keepGoing(self, buf, bufEnd); + default: + return WeaselJson_REJECT; + } + } case '0': case '1': case '2': @@ -1027,25 +1072,9 @@ inline PRESERVE_NONE WeaselJsonStatus n_string(Parser3 *self, char *buf, inline PRESERVE_NONE WeaselJsonStatus n_string2(Parser3 *self, char *buf, char *bufEnd) { - const auto before = buf; - - // Advance buf until double quote, backslash, invalid utf8, or codepoint < - // 0x20 - buf = (char *)self->strDfa.scan(buf, bufEnd); - - int len = buf - before; - memmove(self->writeBuf, before, len); - self->writeBuf += len; - - if (buf == bufEnd) { - self->flushString(false); - return WeaselJson_AGAIN; + if (auto s = n_scan_string(self, buf, bufEnd)) { + return s; } - - if (!self->strDfa.accept()) [[unlikely]] { - return WeaselJson_REJECT; - } - switch (*buf) { case '"': self->flushString(true);