protocol: Use an auto sorting system for message types

Rather than calling sort_lookup externally
This commit is contained in:
Joshua Scott 2018-04-06 04:14:37 +01:00
parent 9ef780ace1
commit b5909878f8
5 changed files with 54 additions and 35 deletions

View File

@ -26,7 +26,8 @@ namespace dml
std::string get_protocol_desription() const; std::string get_protocol_desription() const;
void set_protocol_description(std::string protocol_description); void set_protocol_description(std::string protocol_description);
const MessageTemplate *add_message_template(std::string name, ki::dml::Record *record); const MessageTemplate *add_message_template(std::string name,
ki::dml::Record *record, bool auto_sort = true);
const MessageTemplate *get_message_template(uint8_t type) const; const MessageTemplate *get_message_template(uint8_t type) const;
const MessageTemplate *get_message_template(std::string name) const; const MessageTemplate *get_message_template(std::string name) const;

View File

@ -12,7 +12,8 @@ namespace dml
class MessageTemplate class MessageTemplate
{ {
public: public:
MessageTemplate(std::string name, uint8_t type, ki::dml::Record *record); MessageTemplate(std::string name, uint8_t type,
uint8_t service_id, ki::dml::Record *record);
~MessageTemplate(); ~MessageTemplate();
std::string get_name() const; std::string get_name() const;
@ -21,6 +22,9 @@ namespace dml
uint8_t get_type() const; uint8_t get_type() const;
void set_type(uint8_t type); void set_type(uint8_t type);
uint8_t get_service_id() const;
void set_service_id(uint8_t service_id);
const ki::dml::Record &get_record() const; const ki::dml::Record &get_record() const;
void set_record(ki::dml::Record *record); void set_record(ki::dml::Record *record);
@ -28,6 +32,7 @@ namespace dml
private: private:
std::string m_name; std::string m_name;
uint8_t m_type; uint8_t m_type;
uint8_t m_service_id;
ki::dml::Record *m_record; ki::dml::Record *m_record;
}; };
} }

View File

@ -56,8 +56,6 @@ namespace dml
// It's safe to allocate the module we're working on now // It's safe to allocate the module we're working on now
auto *message_module = new MessageModule(); auto *message_module = new MessageModule();
bool sort_required = true;
bool first_message = true;
// Get the root node and iterate through children // Get the root node and iterate through children
// Each child is a MessageTemplate // Each child is a MessageTemplate
@ -90,16 +88,13 @@ namespace dml
} }
else else
{ {
// Base sorting on whether the first message has the _MsgOrder field. // Only do sorting after we've reached the final message
if (first_message) // This only affects modules that aren't ordered with _MsgOrder.
{ const bool auto_sort = node->next_sibling() == nullptr;
sort_required = !record->has_field("_MsgOrder");
first_message = false;
}
// The template will use the record itself to figure out name and type; // 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. // 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); auto *message_template = message_module->add_message_template(message_name, record, auto_sort);
if (!message_template) if (!message_template)
{ {
delete[] data; delete[] data;
@ -114,10 +109,6 @@ 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 // Make sure we aren't overwriting another module
if (m_service_id_map.count(message_module->get_service_id()) == 1) if (m_service_id_map.count(message_module->get_service_id()) == 1)
{ {

View File

@ -21,6 +21,7 @@ namespace dml
for (auto it = m_templates.begin(); for (auto it = m_templates.begin();
it != m_templates.end(); ++it) it != m_templates.end(); ++it)
delete *it; delete *it;
m_message_type_map.clear();
m_message_name_map.clear(); m_message_name_map.clear();
} }
@ -54,7 +55,8 @@ namespace dml
m_protocol_description = protocol_description; m_protocol_description = protocol_description;
} }
const MessageTemplate *MessageModule::add_message_template(std::string name, ki::dml::Record *record) const MessageTemplate *MessageModule::add_message_template(std::string name,
ki::dml::Record *record, bool auto_sort)
{ {
if (!record) if (!record)
return nullptr; return nullptr;
@ -69,28 +71,33 @@ namespace dml
return m_message_name_map.at(name); return m_message_name_map.at(name);
// Message type is based on the _MsgOrder field if it's present // Message type is based on the _MsgOrder field if it's present
// Otherwise it just goes in order of added templates // Otherwise it's based on the alphabetical order of template names
uint8_t message_type; uint8_t message_type = 0;
auto *order_field = record->get_field<ki::dml::UBYT>("_MsgOrder"); auto *order_field = record->get_field<ki::dml::UBYT>("_MsgOrder");
if (order_field) if (order_field)
{
message_type = order_field->get_value(); message_type = order_field->get_value();
else
message_type = m_last_message_type + 1;
// Don't allow message type to be zero // Don't allow message type to be 0
if (message_type == 0) if (message_type == 0)
return nullptr; return nullptr;
// Do we already have a message template with this type? // Do we already have a template with this type?
if (m_message_type_map.count(message_type) == 1) if (m_message_type_map.count(message_type) == 1)
return nullptr; return nullptr;
}
// Create the template and add it to our maps // Create the message template and add it to our lookups
auto *message_template = new MessageTemplate(name, message_type, record); auto *message_template = new MessageTemplate(name, message_type, m_service_id, record);
m_templates.push_back(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_message_name_map.insert({ name, message_template });
m_last_message_type = message_type;
// Is this module ordered?
if (message_type != 0)
m_message_type_map.insert({ message_type, message_template });
else if (auto_sort)
sort_lookup();
return message_template; return message_template;
} }
@ -125,6 +132,10 @@ namespace dml
message_template->set_type(message_type); message_template->set_type(message_type);
m_message_type_map.insert({ message_type, message_template }); m_message_type_map.insert({ message_type, message_template });
message_type++; message_type++;
// Make sure we haven't overflowed
if (message_type == 0)
throw value_error("Module has more than 254 messages.");
} }
} }
@ -139,8 +150,7 @@ namespace dml
throw value_error(oss.str()); throw value_error(oss.str());
} }
return message_template->build_message() return message_template->build_message();
.set_service_id(m_service_id);
} }
MessageBuilder &MessageModule::build_message(std::string message_name) const MessageBuilder &MessageModule::build_message(std::string message_name) const
@ -154,8 +164,7 @@ namespace dml
throw value_error(oss.str()); throw value_error(oss.str());
} }
return message_template->build_message() return message_template->build_message();
.set_service_id(m_service_id);
} }
} }
} }

View File

@ -6,10 +6,12 @@ namespace protocol
{ {
namespace dml namespace dml
{ {
MessageTemplate::MessageTemplate(std::string name, uint8_t type, ki::dml::Record* record) MessageTemplate::MessageTemplate(std::string name, uint8_t type,
uint8_t service_id, ki::dml::Record* record)
{ {
m_name = name; m_name = name;
m_type = type; m_type = type;
m_service_id = service_id;
m_record = record; m_record = record;
} }
@ -38,6 +40,16 @@ namespace dml
m_type = type; m_type = type;
} }
uint8_t MessageTemplate::get_service_id() const
{
return m_service_id;
}
void MessageTemplate::set_service_id(uint8_t service_id)
{
m_service_id = service_id;
}
const ki::dml::Record& MessageTemplate::get_record() const const ki::dml::Record& MessageTemplate::get_record() const
{ {
return *m_record; return *m_record;
@ -52,6 +64,7 @@ namespace dml
{ {
return MessageBuilder() return MessageBuilder()
.set_message_type(m_type) .set_message_type(m_type)
.set_service_id(m_service_id)
.use_template_record(*m_record); .use_template_record(*m_record);
} }
} }