#include "CommandMap.h" #include "Command.h" #include void CommandMap::add(const char * s, uint32_t id, std::shared_ptr next_map, bool following_char) { size_t length = strlen(s); if (length < 1u) return; std::vector v(length); for (size_t i = 0u; i < length; i++) { v[i] = s[i]; } add(v, id, next_map, following_char); } void CommandMap::add(const std::vector & s, uint32_t id, std::shared_ptr next_map, bool following_char) { Node * node = &m_root_node; size_t length = s.size(); if (length < 1u) return; for (size_t i = 0u; i < length; i++) { const uint32_t c = s[i]; auto it = node->next_chars.find(c); if (it != node->next_chars.end()) { node = &*it->second; } else { auto new_node = std::make_shared(); node->next_chars[c] = new_node; node = &*new_node; } } uint8_t flags = Node::FLAG_TERMINATOR; if (following_char) flags |= Node::FLAG_FOLLOWING_CHAR; node->id = id; node->flags = flags; node->next_map = next_map; } uint8_t CommandMap::lookup_command(const uint32_t * command_characters, size_t length, Command & command) const { std::list units; uint8_t scan_result = scan_units(units, command_characters, length, &m_root_node); if (scan_result == COMMAND_COMPLETE) { int i = 0; for (const auto & unit : units) { switch (i) { case 0: command.main = unit; break; case 1: command.motion = unit; break; } i++; } } return scan_result; } uint8_t CommandMap::scan_units( std::list & units, const uint32_t * command_characters, size_t length, const Node * start_node) const { if (length < 1u) return COMMAND_INCOMPLETE; uint8_t result = COMMAND_INCOMPLETE; uint8_t recurse_result = COMMAND_INVALID; bool gathering_count = true; Command::Unit unit; const Node * node = start_node; for (size_t i = 0u; i < length; i++) { uint32_t c = command_characters[i]; if (gathering_count && ((('1' <= c) && (c <= '9')) || ((c == '0') && (unit.count != 0u)))) { unit.count *= 10u; unit.count += (c - '0'); } else { 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)) { unit.following_char = command_characters[i + 1u]; units.push_front(unit); return COMMAND_COMPLETE; } return COMMAND_INCOMPLETE; } else if (node->next_map) { 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 { units.push_front(unit); return COMMAND_COMPLETE; } } } else { return recurse_result; } } } return result; }