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;
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(std::string name) const;

View File

@ -12,7 +12,8 @@ namespace dml
class MessageTemplate
{
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();
std::string get_name() const;
@ -21,6 +22,9 @@ namespace dml
uint8_t get_type() const;
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;
void set_record(ki::dml::Record *record);
@ -28,6 +32,7 @@ namespace dml
private:
std::string m_name;
uint8_t m_type;
uint8_t m_service_id;
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
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
@ -90,16 +88,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;
}
// Only do sorting after we've reached the final message
// This only affects modules that aren't ordered with _MsgOrder.
const bool auto_sort = node->next_sibling() == nullptr;
// 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);
auto *message_template = message_module->add_message_template(message_name, record, auto_sort);
if (!message_template)
{
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
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();
it != m_templates.end(); ++it)
delete *it;
m_message_type_map.clear();
m_message_name_map.clear();
}
@ -54,7 +55,8 @@ namespace dml
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)
return nullptr;
@ -69,28 +71,33 @@ namespace dml
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
uint8_t message_type;
// Otherwise it's based on the alphabetical order of template names
uint8_t message_type = 0;
auto *order_field = record->get_field<ki::dml::UBYT>("_MsgOrder");
if (order_field)
{
message_type = order_field->get_value();
else
message_type = m_last_message_type + 1;
// Don't allow message type to be zero
if (message_type == 0)
return nullptr;
// Don't allow message type to be 0
if (message_type == 0)
return nullptr;
// Do we already have a message template with this type?
if (m_message_type_map.count(message_type) == 1)
return nullptr;
// Do we already have a template with this type?
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);
// Create the message template and add it to our lookups
auto *message_template = new MessageTemplate(name, message_type, m_service_id, record);
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;
// 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;
}
@ -125,6 +132,10 @@ namespace dml
message_template->set_type(message_type);
m_message_type_map.insert({ message_type, message_template });
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());
}
return message_template->build_message()
.set_service_id(m_service_id);
return message_template->build_message();
}
MessageBuilder &MessageModule::build_message(std::string message_name) const
@ -154,8 +164,7 @@ namespace dml
throw value_error(oss.str());
}
return message_template->build_message()
.set_service_id(m_service_id);
return message_template->build_message();
}
}
}

View File

@ -6,10 +6,12 @@ namespace protocol
{
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_type = type;
m_service_id = service_id;
m_record = record;
}
@ -38,6 +40,16 @@ namespace dml
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
{
return *m_record;
@ -52,6 +64,7 @@ namespace dml
{
return MessageBuilder()
.set_message_type(m_type)
.set_service_id(m_service_id)
.use_template_record(*m_record);
}
}