CommandMap: translate a command character sequence to a Command object
This commit is contained in:
parent
bbc1c8d153
commit
dd84d03b90
@ -32,53 +32,89 @@ void CommandMap::add(const char * s, uint32_t id,
|
|||||||
node->next_map = next_map;
|
node->next_map = next_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Command> CommandMap::get_command(uint32_t * command_characters,
|
uint8_t CommandMap::lookup_command(const uint32_t * command_characters,
|
||||||
uint32_t length) const
|
size_t length, Command & command) const
|
||||||
|
{
|
||||||
|
const Node * node = &m_root_node;
|
||||||
|
for (size_t unit_index = 0u; unit_index < 2u; unit_index++)
|
||||||
|
{
|
||||||
|
size_t consumed_length = 0u;
|
||||||
|
Command::Unit & unit = (unit_index == 0u) ? command.main : command.motion;
|
||||||
|
uint8_t unit_status = extract_command_unit(command_characters,
|
||||||
|
length, unit, node, &node, &consumed_length);
|
||||||
|
switch (unit_status)
|
||||||
|
{
|
||||||
|
case UNIT_INVALID:
|
||||||
|
return COMMAND_INVALID;
|
||||||
|
case UNIT_NEED_MORE_CHARACTERS:
|
||||||
|
return COMMAND_NEED_MORE_CHARACTERS;
|
||||||
|
case UNIT_COMPLETE:
|
||||||
|
return COMMAND_COMPLETE;
|
||||||
|
case UNIT_COMPLETE_NEED_ANOTHER:
|
||||||
|
command_characters += consumed_length;
|
||||||
|
length -= consumed_length;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return COMMAND_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return COMMAND_INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CommandMap::extract_command_unit(const uint32_t * command_characters,
|
||||||
|
size_t length, Command::Unit & unit, const Node * start_node,
|
||||||
|
const Node ** next_node, size_t * consumed_length) const
|
||||||
{
|
{
|
||||||
if (length < 1u)
|
if (length < 1u)
|
||||||
return nullptr;
|
return UNIT_NEED_MORE_CHARACTERS;
|
||||||
const Node * node = &m_root_node;
|
bool gathering_count = true;
|
||||||
bool in_motion = false;
|
unit.count = 0u;
|
||||||
Command command;
|
const Node * node = start_node;
|
||||||
for (size_t i = 0u; i < length; i++)
|
for (size_t i = 0u; i < length; i++)
|
||||||
{
|
{
|
||||||
|
*consumed_length = i + 1u;
|
||||||
uint32_t c = command_characters[i];
|
uint32_t c = command_characters[i];
|
||||||
auto it = node->next_chars.find(c);
|
if (gathering_count && ('0' <= c) && (c <= '9'))
|
||||||
if (it != node->next_chars.end())
|
|
||||||
{
|
{
|
||||||
node = &*it->second;
|
unit.count *= 10u;
|
||||||
if (node->flags & Node::FLAG_TERMINATOR)
|
unit.count += (c - '0');
|
||||||
{
|
|
||||||
if (in_motion)
|
|
||||||
command.motion.id = node->id;
|
|
||||||
else
|
|
||||||
command.main.id = node->id;
|
|
||||||
if (node->flags & Node::FLAG_FOLLOWING_CHAR)
|
|
||||||
{
|
|
||||||
if (i < (length - 1u))
|
|
||||||
{
|
|
||||||
if (in_motion)
|
|
||||||
command.motion.following_char = command_characters[i + 1u];
|
|
||||||
else
|
|
||||||
command.main.following_char = command_characters[i + 1u];
|
|
||||||
return std::make_shared<Command>(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (node->next_map)
|
|
||||||
{
|
|
||||||
in_motion = true;
|
|
||||||
node = &node->next_map->m_root_node;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return std::make_shared<Command>(command);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return nullptr;
|
gathering_count = false;
|
||||||
|
auto it = node->next_chars.find(c);
|
||||||
|
if (it != node->next_chars.end())
|
||||||
|
{
|
||||||
|
node = &*it->second;
|
||||||
|
if (node->flags & Node::FLAG_TERMINATOR)
|
||||||
|
{
|
||||||
|
unit.id = node->id;
|
||||||
|
if (node->flags & Node::FLAG_FOLLOWING_CHAR)
|
||||||
|
{
|
||||||
|
if (i < (length - 1u))
|
||||||
|
{
|
||||||
|
*consumed_length = i + 2u;
|
||||||
|
unit.following_char = command_characters[i + 1u];
|
||||||
|
return UNIT_COMPLETE;
|
||||||
|
}
|
||||||
|
return UNIT_NEED_MORE_CHARACTERS;
|
||||||
|
}
|
||||||
|
else if (node->next_map)
|
||||||
|
{
|
||||||
|
*next_node = &node->next_map->m_root_node;
|
||||||
|
return UNIT_COMPLETE_NEED_ANOTHER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UNIT_COMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return UNIT_INVALID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nullptr;
|
return UNIT_NEED_MORE_CHARACTERS;
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,17 @@
|
|||||||
class CommandMap
|
class CommandMap
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum : uint8_t
|
||||||
|
{
|
||||||
|
COMMAND_INVALID,
|
||||||
|
COMMAND_NEED_MORE_CHARACTERS,
|
||||||
|
COMMAND_COMPLETE,
|
||||||
|
};
|
||||||
|
|
||||||
void add(const char * s, uint32_t id, std::shared_ptr<CommandMap> next_map,
|
void add(const char * s, uint32_t id, std::shared_ptr<CommandMap> next_map,
|
||||||
bool following_char);
|
bool following_char);
|
||||||
std::shared_ptr<Command> get_command(uint32_t * command_characters,
|
uint8_t lookup_command(const uint32_t * command_characters, size_t length,
|
||||||
uint32_t length) const;
|
Command & command) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
struct Node
|
struct Node
|
||||||
@ -36,6 +43,18 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
Node m_root_node;
|
Node m_root_node;
|
||||||
|
|
||||||
|
enum : uint8_t
|
||||||
|
{
|
||||||
|
UNIT_INVALID,
|
||||||
|
UNIT_NEED_MORE_CHARACTERS,
|
||||||
|
UNIT_COMPLETE,
|
||||||
|
UNIT_COMPLETE_NEED_ANOTHER,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t extract_command_unit(const uint32_t * command_characters,
|
||||||
|
size_t length, Command::Unit & unit, const Node * start_node,
|
||||||
|
const Node ** next_node, size_t * consumed_length) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user