Remove stack, just use state machine

This commit is contained in:
2025-08-15 21:55:08 -04:00
parent b67666b97a
commit c55c9f6cd9
2 changed files with 26 additions and 45 deletions

View File

@@ -75,23 +75,18 @@ void CommitRequest::on_begin_object(void *userdata) {
if (ctx.parse_error)
return;
if (ctx.state_stack.empty()) {
ctx.parse_error = "Unexpected object start - empty state stack";
return;
}
ParseState current_state = ctx.state_stack.top();
ParseState current_state = ctx.current_state;
switch (current_state) {
case ParseState::Root:
// Expected - this is the main object
break;
case ParseState::PreconditionsArray:
ctx.state_stack.push(ParseState::PreconditionObject);
ctx.current_state = ParseState::PreconditionObject;
ctx.current_precondition = PreconditionParseState{};
break;
case ParseState::OperationsArray:
ctx.state_stack.push(ParseState::OperationObject);
ctx.current_state = ParseState::OperationObject;
ctx.current_operation = OperationParseState{};
break;
default:
@@ -104,15 +99,18 @@ void CommitRequest::on_end_object(void *userdata) {
auto *self = static_cast<CommitRequest *>(userdata);
auto &ctx = self->parser_context_;
if (ctx.parse_error || ctx.state_stack.empty()) {
if (!ctx.parse_error) {
ctx.parse_error = "Unexpected object end - empty state stack";
}
if (ctx.parse_error) {
return;
}
ParseState current_state = ctx.state_stack.top();
ctx.state_stack.pop();
ParseState current_state = ctx.current_state;
// Handle state transitions on object end
if (current_state == ParseState::PreconditionObject) {
ctx.current_state = ParseState::PreconditionsArray;
} else if (current_state == ParseState::OperationObject) {
ctx.current_state = ParseState::OperationsArray;
}
switch (current_state) {
case ParseState::Root:
@@ -227,10 +225,10 @@ void CommitRequest::on_begin_array(void *userdata) {
if (ctx.current_key == "preconditions") {
ctx.current_key.clear();
ctx.state_stack.push(ParseState::PreconditionsArray);
ctx.current_state = ParseState::PreconditionsArray;
} else if (ctx.current_key == "operations") {
ctx.current_key.clear();
ctx.state_stack.push(ParseState::OperationsArray);
ctx.current_state = ParseState::OperationsArray;
} else {
ctx.parse_error = "Invalid array field - only 'preconditions' and "
"'operations' arrays are allowed";
@@ -241,14 +239,15 @@ void CommitRequest::on_end_array(void *userdata) {
auto *self = static_cast<CommitRequest *>(userdata);
auto &ctx = self->parser_context_;
if (ctx.parse_error || ctx.state_stack.empty()) {
if (!ctx.parse_error) {
ctx.parse_error = "Unexpected array end - empty state stack";
}
if (ctx.parse_error) {
return;
}
ctx.state_stack.pop();
// Transition back to Root state when arrays end
if (ctx.current_state == ParseState::PreconditionsArray ||
ctx.current_state == ParseState::OperationsArray) {
ctx.current_state = ParseState::Root;
}
}
void CommitRequest::on_number_data(void *userdata, const char *buf, int len,
@@ -285,12 +284,7 @@ void CommitRequest::on_null_literal(void *) {
void CommitRequest::handle_completed_string(std::string_view s) {
auto &ctx = parser_context_;
if (ctx.state_stack.empty()) {
ctx.parse_error = "String value received with empty state stack";
return;
}
ParseState current_state = ctx.state_stack.top();
ParseState current_state = ctx.current_state;
switch (current_state) {
case ParseState::Root:
@@ -363,12 +357,7 @@ void CommitRequest::handle_completed_string(std::string_view s) {
void CommitRequest::handle_completed_number(std::string_view s) {
auto &ctx = parser_context_;
if (ctx.state_stack.empty()) {
ctx.parse_error = "Number value received with empty state stack";
return;
}
ParseState current_state = ctx.state_stack.top();
ParseState current_state = ctx.current_state;
switch (current_state) {
case ParseState::Root:

View File

@@ -64,9 +64,6 @@ public:
// Parser state
enum class ParseState {
Root,
RequestId,
LeaderId,
ReadVersion,
PreconditionsArray,
PreconditionObject,
OperationsArray,
@@ -82,12 +79,9 @@ public:
struct ParserContext {
using ArenaString = std::basic_string<char, std::char_traits<char>,
ArenaStlAllocator<char>>;
using ArenaStateStack =
std::stack<ParseState,
std::vector<ParseState, ArenaStlAllocator<ParseState>>>;
ArenaAllocator arena;
ArenaStateStack state_stack;
ParseState current_state = ParseState::Root;
ArenaString current_key;
ArenaString current_string;
ArenaString current_number;
@@ -105,8 +99,7 @@ public:
// Constructor to initialize arena-allocated containers
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)),
@@ -122,8 +115,7 @@ public:
current_operation = {};
precondition_type = ArenaString{ArenaStlAllocator<char>(&arena)};
operation_type = ArenaString{ArenaStlAllocator<char>(&arena)};
state_stack = ArenaStateStack{ArenaStateStack::container_type(
ArenaStlAllocator<ParseState>(&arena))};
current_state = ParseState::Root;
}
};
@@ -313,7 +305,7 @@ public:
WeaselJsonParser_reset(json_parser_);
}
parser_context_.reset_arena_memory();
parser_context_.state_stack.push(ParseState::Root);
parser_context_.current_state = ParseState::Root;
parser_context_.parse_error = nullptr;
parser_context_.parse_complete = false;
}