diff --git a/src/parser3.h b/src/parser3.h index e26e0c1..04dcbd0 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -138,6 +138,12 @@ struct Parser3 { void reset() { stackPtr = stack(); std::ignore = push({N_VALUE, N_WHITESPACE, T_EOF}); + inKey = false; + utf8Codepoint = 0; + utf16Surrogate = 0; + minCodepoint = 0; + numDfa.reset(); + strDfa.reset(); } // Used for flushing pending data with on_*_data callbacks diff --git a/src/test.cpp b/src/test.cpp index 69d81bb..f42f85d 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -223,6 +223,47 @@ TEST_CASE("create rejects too-small stack") { TEST_CASE("streaming") { testStreaming(json); } +TEST_CASE("reset clears inKey and transient state") { + struct State { + std::string stringData; + std::string keyData; + } state; + auto c = noopCallbacks(); + c.on_string_data = +[](void *p, const char *buf, int len, int /*done*/) { + ((State *)p)->stringData.append(buf, len); + }; + c.on_key_data = +[](void *p, const char *buf, int len, int /*done*/) { + ((State *)p)->keyData.append(buf, len); + }; + + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); + REQUIRE(parser != nullptr); + + { + std::string chunk = "{\"ab"; + REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) == + WeaselJson_AGAIN); + } + + // Reset mid-key: the next top-level string must be delivered as a string, + // not appended to the aborted key. + WeaselJsonParser_reset(parser); + state.stringData.clear(); + state.keyData.clear(); + + { + std::string chunk = "\"hello\""; + REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) == + WeaselJson_AGAIN); + } + REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK); + + CHECK(state.stringData == "hello"); + CHECK(state.keyData.empty()); + + WeaselJsonParser_destroy(parser); +} + void doTestUnescapingUtf8(std::string const &escaped, std::string const &expected, int stride, int flags) { CAPTURE(escaped);