Remove stack, just use state machine
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user