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 CommitRequest::finish_streaming_parse() {
CommitRequest::ParseStatus result;
if (!json_parser_) { if (!json_parser_) {
return ParseStatus::Error; result = ParseStatus::Error;
} } else if (parser_context_.parse_error) {
result = 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;
} else { } else {
parser_context_.parse_error =
"JSON parsing incomplete or failed during finalization"; // Signal end of input
return ParseStatus::Error; 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 { struct PreconditionParseState {
Precondition::Type type; Precondition::Type type;
std::optional<uint64_t> version; std::optional<uint64_t> version;
// These are owned by CommitRequest::arena
std::optional<std::string_view> key; std::optional<std::string_view> key;
std::optional<std::string_view> begin; std::optional<std::string_view> begin;
std::optional<std::string_view> end; std::optional<std::string_view> end;
@@ -52,6 +53,7 @@ class CommitRequest {
*/ */
struct OperationParseState { struct OperationParseState {
Operation::Type type; Operation::Type type;
// These are owned by CommitRequest::arena
std::optional<std::string_view> key; std::optional<std::string_view> key;
std::optional<std::string_view> value; std::optional<std::string_view> value;
std::optional<std::string_view> begin; std::optional<std::string_view> begin;
@@ -83,6 +85,7 @@ public:
using ArenaStateStack = using ArenaStateStack =
std::stack<ParseState, std::stack<ParseState,
std::vector<ParseState, ArenaStlAllocator<ParseState>>>; std::vector<ParseState, ArenaStlAllocator<ParseState>>>;
ArenaAllocator arena;
ArenaStateStack state_stack; ArenaStateStack state_stack;
ArenaString current_key; ArenaString current_key;
@@ -101,14 +104,27 @@ public:
ArenaString operation_type; ArenaString operation_type;
// Constructor to initialize arena-allocated containers // Constructor to initialize arena-allocated containers
explicit ParserContext(ArenaAllocator *arena) explicit ParserContext()
: state_stack(ArenaStateStack::container_type( : state_stack(ArenaStateStack::container_type(
ArenaStlAllocator<ParseState>(arena))), ArenaStlAllocator<ParseState>(&arena))),
current_key(ArenaStlAllocator<char>(arena)), current_key(ArenaStlAllocator<char>(&arena)),
current_string(ArenaStlAllocator<char>(arena)), current_string(ArenaStlAllocator<char>(&arena)),
current_number(ArenaStlAllocator<char>(arena)), current_number(ArenaStlAllocator<char>(&arena)),
precondition_type(ArenaStlAllocator<char>(arena)), precondition_type(ArenaStlAllocator<char>(&arena)),
operation_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: private:
@@ -131,8 +147,7 @@ public:
*/ */
explicit CommitRequest() explicit CommitRequest()
: arena_(), preconditions_(ArenaStlAllocator<Precondition>(&arena_)), : arena_(), preconditions_(ArenaStlAllocator<Precondition>(&arena_)),
operations_(ArenaStlAllocator<Operation>(&arena_)), operations_(ArenaStlAllocator<Operation>(&arena_)), parser_context_() {}
parser_context_(&arena_) {}
/** /**
* @brief Destructor - cleans up any active parser. * @brief Destructor - cleans up any active parser.
@@ -297,8 +312,10 @@ public:
if (json_parser_) { if (json_parser_) {
WeaselJsonParser_reset(json_parser_); WeaselJsonParser_reset(json_parser_);
} }
parser_context_ = ParserContext(&arena_); parser_context_.reset_arena_memory();
parser_context_.state_stack.push(ParseState::Root); parser_context_.state_stack.push(ParseState::Root);
parser_context_.parse_error = nullptr;
parser_context_.parse_complete = false;
} }
// Weaseljson callbacks (public for global callbacks) // Weaseljson callbacks (public for global callbacks)