diff --git a/src/parser3.h b/src/parser3.h index 639a05f..91f7b70 100644 --- a/src/parser3.h +++ b/src/parser3.h @@ -83,26 +83,33 @@ struct Parser3 { [[nodiscard]] WeaselJsonStatus parse(char *buf, int len); void flushNumber(bool done, char *buf) { - int len = buf - dataBegin; - assert(len >= 0); - if (done || len > 0) { - callbacks->on_number_data(userdata, dataBegin, len, done); - } - } - - void flushString(bool done, char *buf) { - int len; - if (!(flags & WeaselJsonRaw)) { - len = writeBuf - dataBegin; - } else { + int len = 0; + if (dataBegin != nullptr && buf != nullptr) { len = buf - dataBegin; } assert(len >= 0); if (done || len > 0) { + callbacks->on_number_data(userdata, dataBegin ? dataBegin : "", len, + done); + } + } + + void flushString(bool done, char *buf) { + int len = 0; + if (dataBegin != nullptr) { + if (!(flags & WeaselJsonRaw)) { + len = writeBuf - dataBegin; + } else if (buf != nullptr) { + len = buf - dataBegin; + } + } + assert(len >= 0); + if (done || len > 0) { + const char *data = dataBegin ? dataBegin : ""; if (inKey) { - callbacks->on_key_data(userdata, dataBegin, len, done); + callbacks->on_key_data(userdata, data, len, done); } else { - callbacks->on_string_data(userdata, dataBegin, len, done); + callbacks->on_string_data(userdata, data, len, done); } } } diff --git a/src/test.cpp b/src/test.cpp index eec6669..792cafa 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -303,6 +303,24 @@ TEST_CASE("reset clears inKey and transient state") { WeaselJsonParser_destroy(parser); } +TEST_CASE("scalar ending at chunk boundary is finalized at EOF") { + // A number whose digits exactly fill the first chunk must not invoke + // undefined behaviour on the EOF call, and must still signal completion. + auto c = serializeCallbacks(); + SerializeState state; + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); + REQUIRE(parser != nullptr); + + std::string chunk = "123"; + REQUIRE(WeaselJsonParser_parse(parser, chunk.data(), chunk.size()) == + WeaselJson_AGAIN); + REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK); + + CHECK(state.result == "(123)"); + + WeaselJsonParser_destroy(parser); +} + void doTestUnescapingUtf8(std::string const &escaped, std::string const &expected, int stride, int flags) { CAPTURE(escaped);