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

View File

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