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)
|
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:
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user