diff --git a/include/ki/protocol/dml/MessageModule.h b/include/ki/protocol/dml/MessageModule.h index 94d4e38..b92c3b1 100644 --- a/include/ki/protocol/dml/MessageModule.h +++ b/include/ki/protocol/dml/MessageModule.h @@ -3,7 +3,6 @@ #include #include #include -#include #include namespace ki @@ -31,6 +30,8 @@ namespace dml const MessageTemplate *get_message_template(uint8_t type) const; const MessageTemplate *get_message_template(std::string name) const; + void sort_lookup(); + MessageBuilder &build_message(uint8_t message_type) const; MessageBuilder &build_message(std::string message_name) const; private: @@ -39,7 +40,8 @@ namespace dml std::string m_protocol_description; uint8_t m_last_message_type; - std::array m_templates; + std::vector m_templates; + std::map m_message_type_map; std::map m_message_name_map; }; diff --git a/src/protocol/dml/MessageManager.cpp b/src/protocol/dml/MessageManager.cpp index 73eee25..3afc052 100644 --- a/src/protocol/dml/MessageManager.cpp +++ b/src/protocol/dml/MessageManager.cpp @@ -56,6 +56,8 @@ namespace dml // It's safe to allocate the module we're working on now auto *message_module = new MessageModule(); + bool sort_required = true; + bool first_message = true; // Get the root node and iterate through children // Each child is a MessageTemplate @@ -88,6 +90,13 @@ namespace dml } else { + // Base sorting on whether the first message has the _MsgOrder field. + if (first_message) + { + sort_required = !record->has_field("_MsgOrder"); + first_message = false; + } + // The template will use the record itself to figure out name and type; // we only give the XML data incase the record doesn't have it defined. auto *message_template = message_module->add_message_template(message_name, record); @@ -105,6 +114,10 @@ namespace dml } } + // Sort the module's lookup if we need to + if (sort_required) + message_module->sort_lookup(); + // Make sure we aren't overwriting another module if (m_service_id_map.count(message_module->get_service_id()) == 1) { diff --git a/src/protocol/dml/MessageModule.cpp b/src/protocol/dml/MessageModule.cpp index 4d2c626..c02739d 100644 --- a/src/protocol/dml/MessageModule.cpp +++ b/src/protocol/dml/MessageModule.cpp @@ -14,7 +14,6 @@ namespace dml m_protocol_type = protocol_type; m_protocol_description = ""; m_last_message_type = 0; - m_templates = std::array { nullptr }; } MessageModule::~MessageModule() @@ -67,7 +66,7 @@ namespace dml // Do we already have a message template with this name? if (m_message_name_map.count(name) == 1) - return nullptr; + return m_message_name_map.at(name); // Message type is based on the _MsgOrder field if it's present // Otherwise it just goes in order of added templates @@ -83,12 +82,13 @@ namespace dml return nullptr; // Do we already have a message template with this type? - if (m_templates[message_type] != nullptr) + if (m_message_type_map.count(message_type) == 1) return nullptr; // Create the template and add it to our maps auto *message_template = new MessageTemplate(name, message_type, record); - m_templates[message_type] = message_template; + m_templates.push_back(message_template); + m_message_type_map.insert({ message_type, message_template }); m_message_name_map.insert({ name, message_template }); m_last_message_type = message_type; return message_template; @@ -96,7 +96,9 @@ namespace dml const MessageTemplate *MessageModule::get_message_template(uint8_t type) const { - return m_templates[type]; + if (m_message_type_map.count(type) == 1) + return m_message_type_map.at(type); + return nullptr; } const MessageTemplate *MessageModule::get_message_template(std::string name) const @@ -106,6 +108,26 @@ namespace dml return nullptr; } + void MessageModule::sort_lookup() + { + uint8_t message_type = 1; + + // First, clear the message type map since we're going to be + // moving everything around + m_message_type_map.clear(); + + // Iterating over a map with std::string as the key + // is guaranteed to be in alphabetical order + for (auto it = m_message_name_map.begin(); + it != m_message_name_map.end(); ++it) + { + auto *message_template = it->second; + message_template->set_type(message_type); + m_message_type_map.insert({ message_type, message_template }); + message_type++; + } + } + MessageBuilder& MessageModule::build_message(uint8_t message_type) const { auto *message_template = get_message_template(message_type);