CommandMap: recurse to resolve command sequences properly

This commit is contained in:
josh committed 2017-10-30 20:21:51 -04:00
1 parent dd84d03b90
commit 54bbfefcf4
5 files changed
+224 -47

No files matched your search

+12
View File
@@ -1,2 +1,14 @@
#include "Command.h"
#include <string.h>
bool Command::Unit::operator==(const Command::Unit & other) const
{
return (id == other.id) &&
(count == other.count) &&
(following_char == other.following_char);
}
bool Command::operator==(const Command & other) const
{
return (main == other.main) && (motion == other.motion);
}
+4
View File
@@ -47,10 +47,14 @@ public:
count = 0u;
following_char = 0u;
}
bool operator==(const Unit & other) const;
};
Unit main;
Unit motion;
bool operator==(const Command & other) const;
};
#endif
+40 -34
View File
@@ -35,44 +35,42 @@ void CommandMap::add(const char * s, uint32_t id,
uint8_t CommandMap::lookup_command(const uint32_t * command_characters,
size_t length, Command & command) const
{
const Node * node = &m_root_node;
for (size_t unit_index = 0u; unit_index < 2u; unit_index++)
std::list<Command::Unit> units;
uint8_t scan_result = scan_units(units, command_characters, length, &m_root_node);
if (scan_result == COMMAND_COMPLETE)
{
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)
int i = 0;
for (const auto & unit : units)
{
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;
switch (i)
{
case 0:
command.main = unit;
break;
case 1:
command.motion = unit;
break;
}
i++;
}
}
return COMMAND_INVALID;
return scan_result;
}
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
uint8_t CommandMap::scan_units(
std::list<Command::Unit> & units,
const uint32_t * command_characters, size_t length,
const Node * start_node) const
{
if (length < 1u)
return UNIT_NEED_MORE_CHARACTERS;
return COMMAND_INCOMPLETE;
uint8_t result = COMMAND_INCOMPLETE;
uint8_t recurse_result = COMMAND_INVALID;
bool gathering_count = true;
unit.count = 0u;
Command::Unit unit;
const Node * node = start_node;
for (size_t i = 0u; i < length; i++)
{
*consumed_length = i + 1u;
uint32_t c = command_characters[i];
if (gathering_count && ('0' <= c) && (c <= '9'))
{
@@ -93,28 +91,36 @@ uint8_t CommandMap::extract_command_unit(const uint32_t * command_characters,
{
if (i < (length - 1u))
{
*consumed_length = i + 2u;
unit.following_char = command_characters[i + 1u];
return UNIT_COMPLETE;
units.push_front(unit);
return COMMAND_COMPLETE;
}
return UNIT_NEED_MORE_CHARACTERS;
return COMMAND_INCOMPLETE;
}
else if (node->next_map)
{
*next_node = &node->next_map->m_root_node;
return UNIT_COMPLETE_NEED_ANOTHER;
recurse_result = scan_units(units,
&command_characters[i + 1u],
length - i - 1u, &node->next_map->m_root_node);
if (recurse_result == COMMAND_COMPLETE)
{
units.push_front(unit);
return COMMAND_COMPLETE;
}
result = recurse_result;
}
else
{
return UNIT_COMPLETE;
units.push_front(unit);
return COMMAND_COMPLETE;
}
}
}
else
{
return UNIT_INVALID;
return recurse_result;
}
}
}
return UNIT_NEED_MORE_CHARACTERS;
return result;
}
+6 -13
View File
@@ -2,8 +2,8 @@
#define COMMANDMAP_H
#include <unordered_map>
#include <vector>
#include <memory>
#include <list>
#include "Command.h"
class CommandMap
@@ -12,7 +12,7 @@ public:
enum : uint8_t
{
COMMAND_INVALID,
COMMAND_NEED_MORE_CHARACTERS,
COMMAND_INCOMPLETE,
COMMAND_COMPLETE,
};
@@ -44,17 +44,10 @@ protected:
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;
uint8_t scan_units(
std::list<Command::Unit> & units,
const uint32_t * command_characters, size_t length,
const Node * start_node) const;
};
#endif