diff --git a/include/weaseljson.h b/include/weaseljson.h index 1442376..93d734b 100644 --- a/include/weaseljson.h +++ b/include/weaseljson.h @@ -36,13 +36,18 @@ enum WeaselJsonStatus { typedef struct WeaselJsonParser WeaselJsonParser; +enum WeaselJsonFlags { + /** Do not unescape strings or write to the supplied buffer at all. */ + WeaselJsonRaw = 1, +}; + /** Create a parser. Increasing stack size increases memory usage but also * increases the depth of nested json accepted. `callbacks` and `userdata` must * outlive the returned parser. Returns null if there's insufficient available * memory */ WeaselJsonParser *WeaselJsonParser_create(int stackSize, const WeaselJsonCallbacks *callbacks, - void *userdata); + void *userdata, int flags); /** Restore the parser to its newly-created state */ void WeaselJsonParser_reset(WeaselJsonParser *parser); diff --git a/src/fuzz.cpp b/src/fuzz.cpp index af3afdf..713c9f1 100644 --- a/src/fuzz.cpp +++ b/src/fuzz.cpp @@ -10,7 +10,7 @@ std::pair runStreaming(std::string copy, SerializeState state; auto c = serializeCallbacks(); std::unique_ptr parser{ - WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; + WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy}; if (stride == 0) { auto s = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()); if (s != WeaselJson_AGAIN) { @@ -33,7 +33,7 @@ std::pair runBatch(std::string copy) { SerializeState state; auto c = serializeCallbacks(); std::unique_ptr parser{ - WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; + WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy}; auto s = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()); if (s != WeaselJson_AGAIN) { return {state.result, s}; @@ -47,7 +47,7 @@ std::pair runPrefix(std::string copy, SerializeState state; auto c = serializeCallbacks(); std::unique_ptr parser{ - WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; + WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy}; auto s = WeaselJsonParser_parse(parser.get(), copy.data(), prefix); if (s != WeaselJson_AGAIN) { return {state.result, s}; @@ -116,7 +116,7 @@ void compareWithSimdjson(std::string const &json) { auto copy = json; auto c = noopCallbacks(); std::unique_ptr - parser{WeaselJsonParser_create(1024, &c, nullptr), + parser{WeaselJsonParser_create(1024, &c, nullptr, 0), WeaselJsonParser_destroy}; ours = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()); if (ours == WeaselJson_AGAIN) { diff --git a/src/json_value.h b/src/json_value.h index 496ed35..76b79f9 100644 --- a/src/json_value.h +++ b/src/json_value.h @@ -196,7 +196,7 @@ inline std::optional toValue(std::string copy, int stride) { ReadValueState state; auto c = readValueCallbacks(); std::unique_ptr parser{ - WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; + WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy}; if (stride == 0) { if (WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()) != WeaselJson_AGAIN) { diff --git a/src/lib.cpp b/src/lib.cpp index 24040f5..8b8b277 100644 --- a/src/lib.cpp +++ b/src/lib.cpp @@ -7,7 +7,7 @@ extern "C" { __attribute__((visibility("default"))) WeaselJsonParser * WeaselJsonParser_create(int stackSize, const WeaselJsonCallbacks *callbacks, - void *userdata) { + void *userdata, int flags) { auto *buf = malloc(sizeof(Parser3) + stackSize * sizeof(*Parser3::stackPtr)); if (buf == nullptr) { return nullptr; diff --git a/src/test.cpp b/src/test.cpp index ee8f1d7..a263009 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -133,7 +133,7 @@ void testStreaming(std::string const &json) { auto c = serializeCallbacks(); { auto copy = json; - auto *parser = WeaselJsonParser_create(1024, &c, &streaming); + auto *parser = WeaselJsonParser_create(1024, &c, &streaming, 0); for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); @@ -143,7 +143,7 @@ void testStreaming(std::string const &json) { } { auto copy = json; - auto *parser = WeaselJsonParser_create(1024, &c, &batch); + auto *parser = WeaselJsonParser_create(1024, &c, &batch, 0); REQUIRE(WeaselJsonParser_parse(parser, copy.data(), copy.size()) == WeaselJson_AGAIN); REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK); @@ -159,7 +159,7 @@ TEST_CASE("parser3") { SerializeState state; { auto copy = json; - auto *parser = WeaselJsonParser_create(1024, &c, &state); + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); @@ -169,7 +169,7 @@ TEST_CASE("parser3") { } { std::string copy = "{\"x\": [], \"y\": {}}"; - auto *parser = WeaselJsonParser_create(1024, &c, &state); + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); @@ -181,7 +181,7 @@ TEST_CASE("parser3") { { auto c = noopCallbacks(); std::string copy = "{\"a\":\"a"; - auto *parser = WeaselJsonParser_create(1024, &c, &state); + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); @@ -192,7 +192,7 @@ TEST_CASE("parser3") { { auto c = noopCallbacks(); std::string copy = "["; - auto *parser = WeaselJsonParser_create(1024, &c, &state); + auto *parser = WeaselJsonParser_create(1024, &c, &state, 0); for (size_t i = 0; i < copy.size(); ++i) { REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == WeaselJson_AGAIN); @@ -215,7 +215,7 @@ void doTestUnescapingUtf8(std::string const &escaped, auto &s = *(std::string *)p; s.append(buf, len); }; - auto *parser = WeaselJsonParser_create(1024, &c, &result); + auto *parser = WeaselJsonParser_create(1024, &c, &result, 0); auto copy = escaped; for (size_t i = 0; i < copy.size(); i += stride) { CAPTURE(i); @@ -262,7 +262,7 @@ TEST_CASE("bench3") { ankerl::nanobench::Bench bench; bench.batch(json.size()); bench.unit("byte"); - auto *parser = WeaselJsonParser_create(1024, &c, nullptr); + auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0); for (size_t stride = 128; stride <= json.size(); stride *= 2) { bench.run("parser3 (stride: " + std::to_string(stride) + ")", [&]() { auto copy = json; @@ -376,7 +376,7 @@ TEST_CASE("bench input types") { bench.doNotOptimizeAway(doc); }); - auto *parser = WeaselJsonParser_create(1024, &c, nullptr); + auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0); bench.run("parser3 " + name, [&]() { auto copy = json; WeaselJsonParser_reset(parser); diff --git a/src/validate.cpp b/src/validate.cpp index 42425da..abbd2fa 100644 --- a/src/validate.cpp +++ b/src/validate.cpp @@ -17,7 +17,7 @@ int main(int argc, char **argv) { } auto c = noopCallbacks(); std::unique_ptr parser{ - WeaselJsonParser_create(1024, &c, nullptr), WeaselJsonParser_destroy}; + WeaselJsonParser_create(1024, &c, nullptr, 0), WeaselJsonParser_destroy}; for (;;) { char buf[1024]; int l = read(fd, buf, sizeof(buf)); diff --git a/weaseljson.py b/weaseljson.py index 405e10c..a39d953 100644 --- a/weaseljson.py +++ b/weaseljson.py @@ -92,6 +92,7 @@ class WeaselJsonParser: ctypes.c_int, ctypes.POINTER(WeaselJsonCallbacks), ctypes.c_void_p, + ctypes.c_int, ) self._lib.WeaselJsonParser_create.restype = ctypes.c_void_p self._lib.WeaselJsonParser_reset.argtypes = (ctypes.c_void_p,) @@ -110,6 +111,7 @@ class WeaselJsonParser: stackSize, c_callbacks, self.voidp_callbacks, + 0, ) def parse(self, data: bytes) -> WeaselJsonStatus: