Add flags argument to WeaselJsonParser_create

This commit is contained in:
2025-06-25 16:44:31 -04:00
parent 01d81981f7
commit 3e72181bee
7 changed files with 24 additions and 17 deletions

View File

@@ -36,13 +36,18 @@ enum WeaselJsonStatus {
typedef struct WeaselJsonParser WeaselJsonParser; 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 /** Create a parser. Increasing stack size increases memory usage but also
* increases the depth of nested json accepted. `callbacks` and `userdata` must * increases the depth of nested json accepted. `callbacks` and `userdata` must
* outlive the returned parser. Returns null if there's insufficient available * outlive the returned parser. Returns null if there's insufficient available
* memory */ * memory */
WeaselJsonParser *WeaselJsonParser_create(int stackSize, WeaselJsonParser *WeaselJsonParser_create(int stackSize,
const WeaselJsonCallbacks *callbacks, const WeaselJsonCallbacks *callbacks,
void *userdata); void *userdata, int flags);
/** Restore the parser to its newly-created state */ /** Restore the parser to its newly-created state */
void WeaselJsonParser_reset(WeaselJsonParser *parser); void WeaselJsonParser_reset(WeaselJsonParser *parser);

View File

@@ -10,7 +10,7 @@ std::pair<std::string, WeaselJsonStatus> runStreaming(std::string copy,
SerializeState state; SerializeState state;
auto c = serializeCallbacks(); auto c = serializeCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{ std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{
WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy};
if (stride == 0) { if (stride == 0) {
auto s = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()); auto s = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size());
if (s != WeaselJson_AGAIN) { if (s != WeaselJson_AGAIN) {
@@ -33,7 +33,7 @@ std::pair<std::string, WeaselJsonStatus> runBatch(std::string copy) {
SerializeState state; SerializeState state;
auto c = serializeCallbacks(); auto c = serializeCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{ std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> 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()); auto s = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size());
if (s != WeaselJson_AGAIN) { if (s != WeaselJson_AGAIN) {
return {state.result, s}; return {state.result, s};
@@ -47,7 +47,7 @@ std::pair<std::string, WeaselJsonStatus> runPrefix(std::string copy,
SerializeState state; SerializeState state;
auto c = serializeCallbacks(); auto c = serializeCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{ std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> 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); auto s = WeaselJsonParser_parse(parser.get(), copy.data(), prefix);
if (s != WeaselJson_AGAIN) { if (s != WeaselJson_AGAIN) {
return {state.result, s}; return {state.result, s};
@@ -116,7 +116,7 @@ void compareWithSimdjson(std::string const &json) {
auto copy = json; auto copy = json;
auto c = noopCallbacks(); auto c = noopCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)>
parser{WeaselJsonParser_create(1024, &c, nullptr), parser{WeaselJsonParser_create(1024, &c, nullptr, 0),
WeaselJsonParser_destroy}; WeaselJsonParser_destroy};
ours = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()); ours = WeaselJsonParser_parse(parser.get(), copy.data(), copy.size());
if (ours == WeaselJson_AGAIN) { if (ours == WeaselJson_AGAIN) {

View File

@@ -196,7 +196,7 @@ inline std::optional<JsonValue> toValue(std::string copy, int stride) {
ReadValueState state; ReadValueState state;
auto c = readValueCallbacks(); auto c = readValueCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{ std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{
WeaselJsonParser_create(1024, &c, &state), WeaselJsonParser_destroy}; WeaselJsonParser_create(1024, &c, &state, 0), WeaselJsonParser_destroy};
if (stride == 0) { if (stride == 0) {
if (WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()) != if (WeaselJsonParser_parse(parser.get(), copy.data(), copy.size()) !=
WeaselJson_AGAIN) { WeaselJson_AGAIN) {

View File

@@ -7,7 +7,7 @@ extern "C" {
__attribute__((visibility("default"))) WeaselJsonParser * __attribute__((visibility("default"))) WeaselJsonParser *
WeaselJsonParser_create(int stackSize, const WeaselJsonCallbacks *callbacks, WeaselJsonParser_create(int stackSize, const WeaselJsonCallbacks *callbacks,
void *userdata) { void *userdata, int flags) {
auto *buf = malloc(sizeof(Parser3) + stackSize * sizeof(*Parser3::stackPtr)); auto *buf = malloc(sizeof(Parser3) + stackSize * sizeof(*Parser3::stackPtr));
if (buf == nullptr) { if (buf == nullptr) {
return nullptr; return nullptr;

View File

@@ -133,7 +133,7 @@ void testStreaming(std::string const &json) {
auto c = serializeCallbacks(); auto c = serializeCallbacks();
{ {
auto copy = json; 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) { for (size_t i = 0; i < copy.size(); ++i) {
REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
@@ -143,7 +143,7 @@ void testStreaming(std::string const &json) {
} }
{ {
auto copy = 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()) == REQUIRE(WeaselJsonParser_parse(parser, copy.data(), copy.size()) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK); REQUIRE(WeaselJsonParser_parse(parser, nullptr, 0) == WeaselJson_OK);
@@ -159,7 +159,7 @@ TEST_CASE("parser3") {
SerializeState state; SerializeState state;
{ {
auto copy = json; 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) { for (size_t i = 0; i < copy.size(); ++i) {
REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
@@ -169,7 +169,7 @@ TEST_CASE("parser3") {
} }
{ {
std::string copy = "{\"x\": [], \"y\": {}}"; 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) { for (size_t i = 0; i < copy.size(); ++i) {
REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
@@ -181,7 +181,7 @@ TEST_CASE("parser3") {
{ {
auto c = noopCallbacks(); auto c = noopCallbacks();
std::string copy = "{\"a\":\"a"; 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) { for (size_t i = 0; i < copy.size(); ++i) {
REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
@@ -192,7 +192,7 @@ TEST_CASE("parser3") {
{ {
auto c = noopCallbacks(); auto c = noopCallbacks();
std::string copy = "["; 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) { for (size_t i = 0; i < copy.size(); ++i) {
REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) == REQUIRE(WeaselJsonParser_parse(parser, copy.data() + i, 1) ==
WeaselJson_AGAIN); WeaselJson_AGAIN);
@@ -215,7 +215,7 @@ void doTestUnescapingUtf8(std::string const &escaped,
auto &s = *(std::string *)p; auto &s = *(std::string *)p;
s.append(buf, len); s.append(buf, len);
}; };
auto *parser = WeaselJsonParser_create(1024, &c, &result); auto *parser = WeaselJsonParser_create(1024, &c, &result, 0);
auto copy = escaped; auto copy = escaped;
for (size_t i = 0; i < copy.size(); i += stride) { for (size_t i = 0; i < copy.size(); i += stride) {
CAPTURE(i); CAPTURE(i);
@@ -262,7 +262,7 @@ TEST_CASE("bench3") {
ankerl::nanobench::Bench bench; ankerl::nanobench::Bench bench;
bench.batch(json.size()); bench.batch(json.size());
bench.unit("byte"); 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) { for (size_t stride = 128; stride <= json.size(); stride *= 2) {
bench.run("parser3 (stride: " + std::to_string(stride) + ")", [&]() { bench.run("parser3 (stride: " + std::to_string(stride) + ")", [&]() {
auto copy = json; auto copy = json;
@@ -376,7 +376,7 @@ TEST_CASE("bench input types") {
bench.doNotOptimizeAway(doc); bench.doNotOptimizeAway(doc);
}); });
auto *parser = WeaselJsonParser_create(1024, &c, nullptr); auto *parser = WeaselJsonParser_create(1024, &c, nullptr, 0);
bench.run("parser3 " + name, [&]() { bench.run("parser3 " + name, [&]() {
auto copy = json; auto copy = json;
WeaselJsonParser_reset(parser); WeaselJsonParser_reset(parser);

View File

@@ -17,7 +17,7 @@ int main(int argc, char **argv) {
} }
auto c = noopCallbacks(); auto c = noopCallbacks();
std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{ std::unique_ptr<WeaselJsonParser, decltype(&WeaselJsonParser_destroy)> parser{
WeaselJsonParser_create(1024, &c, nullptr), WeaselJsonParser_destroy}; WeaselJsonParser_create(1024, &c, nullptr, 0), WeaselJsonParser_destroy};
for (;;) { for (;;) {
char buf[1024]; char buf[1024];
int l = read(fd, buf, sizeof(buf)); int l = read(fd, buf, sizeof(buf));

View File

@@ -92,6 +92,7 @@ class WeaselJsonParser:
ctypes.c_int, ctypes.c_int,
ctypes.POINTER(WeaselJsonCallbacks), ctypes.POINTER(WeaselJsonCallbacks),
ctypes.c_void_p, ctypes.c_void_p,
ctypes.c_int,
) )
self._lib.WeaselJsonParser_create.restype = ctypes.c_void_p self._lib.WeaselJsonParser_create.restype = ctypes.c_void_p
self._lib.WeaselJsonParser_reset.argtypes = (ctypes.c_void_p,) self._lib.WeaselJsonParser_reset.argtypes = (ctypes.c_void_p,)
@@ -110,6 +111,7 @@ class WeaselJsonParser:
stackSize, stackSize,
c_callbacks, c_callbacks,
self.voidp_callbacks, self.voidp_callbacks,
0,
) )
def parse(self, data: bytes) -> WeaselJsonStatus: def parse(self, data: bytes) -> WeaselJsonStatus: