Separate arena for state during parsing

This commit is contained in:
2025-08-15 15:19:24 -04:00
parent 0f72aded89
commit 4e8d3a4c61
2 changed files with 48 additions and 26 deletions

View File

@@ -495,23 +495,28 @@ CommitRequest::ParseStatus CommitRequest::parse_chunk(char *data, size_t len) {
}
CommitRequest::ParseStatus CommitRequest::finish_streaming_parse() {
CommitRequest::ParseStatus result;
if (!json_parser_) {
return ParseStatus::Error;
}
if (parser_context_.parse_error) {
return ParseStatus::Error;
}
// Signal end of input
WeaselJsonStatus status = WeaselJsonParser_parse(json_parser_, nullptr, 0);
if (status == WeaselJson_OK && parser_context_.parse_complete &&
!parser_context_.parse_error) {
return ParseStatus::Complete;
result = ParseStatus::Error;
} else if (parser_context_.parse_error) {
result = ParseStatus::Error;
} else {
parser_context_.parse_error =
"JSON parsing incomplete or failed during finalization";
return ParseStatus::Error;
// Signal end of input
WeaselJsonStatus status = WeaselJsonParser_parse(json_parser_, nullptr, 0);
if (status == WeaselJson_OK && parser_context_.parse_complete &&
!parser_context_.parse_error) {
result = ParseStatus::Complete;
} else {
parser_context_.parse_error =
"JSON parsing incomplete or failed during finalization";
result = ParseStatus::Error;
}
}
// Clear the memory used only during parsing
parser_context_.reset_arena_memory();
return result;
}

View File

@@ -42,6 +42,7 @@ class CommitRequest {
struct PreconditionParseState {
Precondition::Type type;
std::optional<uint64_t> version;
// These are owned by CommitRequest::arena
std::optional<std::string_view> key;
std::optional<std::string_view> begin;
std::optional<std::string_view> end;
@@ -52,6 +53,7 @@ class CommitRequest {
*/
struct OperationParseState {
Operation::Type type;
// These are owned by CommitRequest::arena
std::optional<std::string_view> key;
std::optional<std::string_view> value;
std::optional<std::string_view> begin;
@@ -83,6 +85,7 @@ public:
using ArenaStateStack =
std::stack<ParseState,
std::vector<ParseState, ArenaStlAllocator<ParseState>>>;
ArenaAllocator arena;
ArenaStateStack state_stack;
ArenaString current_key;
@@ -101,14 +104,27 @@ public:
ArenaString operation_type;
// Constructor to initialize arena-allocated containers
explicit ParserContext(ArenaAllocator *arena)
explicit ParserContext()
: state_stack(ArenaStateStack::container_type(
ArenaStlAllocator<ParseState>(arena))),
current_key(ArenaStlAllocator<char>(arena)),
current_string(ArenaStlAllocator<char>(arena)),
current_number(ArenaStlAllocator<char>(arena)),
precondition_type(ArenaStlAllocator<char>(arena)),
operation_type(ArenaStlAllocator<char>(arena)) {}
ArenaStlAllocator<ParseState>(&arena))),
current_key(ArenaStlAllocator<char>(&arena)),
current_string(ArenaStlAllocator<char>(&arena)),
current_number(ArenaStlAllocator<char>(&arena)),
precondition_type(ArenaStlAllocator<char>(&arena)),
operation_type(ArenaStlAllocator<char>(&arena)) {}
void reset_arena_memory() {
arena.reset();
current_key = ArenaString{ArenaStlAllocator<char>(&arena)};
current_string = ArenaString{ArenaStlAllocator<char>(&arena)};
current_number = ArenaString{ArenaStlAllocator<char>(&arena)};
in_key = false;
current_precondition = {};
current_operation = {};
precondition_type = ArenaString{ArenaStlAllocator<char>(&arena)};
operation_type = ArenaString{ArenaStlAllocator<char>(&arena)};
state_stack = ArenaStateStack{ArenaStateStack::container_type(
ArenaStlAllocator<ParseState>(&arena))};
}
};
private:
@@ -131,8 +147,7 @@ public:
*/
explicit CommitRequest()
: arena_(), preconditions_(ArenaStlAllocator<Precondition>(&arena_)),
operations_(ArenaStlAllocator<Operation>(&arena_)),
parser_context_(&arena_) {}
operations_(ArenaStlAllocator<Operation>(&arena_)), parser_context_() {}
/**
* @brief Destructor - cleans up any active parser.
@@ -297,8 +312,10 @@ public:
if (json_parser_) {
WeaselJsonParser_reset(json_parser_);
}
parser_context_ = ParserContext(&arena_);
parser_context_.reset_arena_memory();
parser_context_.state_stack.push(ParseState::Root);
parser_context_.parse_error = nullptr;
parser_context_.parse_complete = false;
}
// Weaseljson callbacks (public for global callbacks)