diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index ca25113f..13cfcb9d 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -27,6 +27,9 @@ using namespace std; +/** the bit mask of the source master number in the message key. */ +#define ID_SOURCE_MASK (0x1fLL << (8 * 7)) + Message::Message(const string clazz, const string name, const bool isSet, const bool isPassive, const string comment, const unsigned char srcAddress, const unsigned char dstAddress, @@ -338,38 +341,39 @@ bool Message::isLessPollWeight(Message* other) { result_t MessageMap::add(Message* message) { - unsigned long long pkey = message->getKey(); - bool isPassive = message->isPassive(); - if (isPassive == true) { - map::iterator keyIt = m_passiveMessagesByKey.find(pkey); - if (keyIt != m_passiveMessagesByKey.end()) { - return RESULT_ERR_DUPLICATE; // duplicate key - } + unsigned long long key = message->getKey(); + map::iterator keyIt = m_messagesByKey.find(key); + if (keyIt != m_messagesByKey.end()) { + return RESULT_ERR_DUPLICATE; // duplicate key } + bool isPassive = message->isPassive(); bool isSet = message->isSet(); string clazz = message->getClass(); string name = message->getName(); - string key = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + FIELD_SEPARATOR + name; - map::iterator nameIt = m_messagesByName.find(key); + string nameKey = string(isPassive ? "P" : (isSet ? "W" : "R")) + clazz + FIELD_SEPARATOR + name; + map::iterator nameIt = m_messagesByName.find(nameKey); if (nameIt != m_messagesByName.end()) { return RESULT_ERR_DUPLICATE; // duplicate key } - m_messagesByName[key] = message; + m_messagesByName[nameKey] = message; m_messageCount++; + if (isPassive == true) + m_passiveMessageCount++; - key = string(isPassive ? "-P" : (isSet ? "-W" : "-R")) + name; // also store without class - m_messagesByName[key] = message; // last key without class overrides previous - - if (message->isPassive() == true) { - unsigned char idLength = message->getId().size() - 2; - if (idLength < m_minIdLength) - m_minIdLength = idLength; - if (idLength > m_maxIdLength) - m_maxIdLength = idLength; - m_passiveMessagesByKey[pkey] = message; + nameKey = string(isPassive ? "-P" : (isSet ? "-W" : "-R")) + name; // also store without class + nameIt = m_messagesByName.find(nameKey); + if (nameIt == m_messagesByName.end()) { + m_messagesByName[nameKey] = message; // only store first key without class } + unsigned char idLength = message->getId().size() - 2; + if (idLength < m_minIdLength) + m_minIdLength = idLength; + if (idLength > m_maxIdLength) + m_maxIdLength = idLength; + m_messagesByKey[key] = message; + if (message->getPollPriority() > 0) m_pollMessages.push(message); @@ -462,7 +466,6 @@ Message* MessageMap::find(SymbolString& master) if (master.size() < 5+maxIdLength) return NULL; - unsigned long long sourceMask = 0x1fLL << (8 * 7); for (int idLength = maxIdLength; idLength >= m_minIdLength; idLength--) { int exp = 7; unsigned long long key = (unsigned long long)idLength << (8 * exp + 5); @@ -473,16 +476,19 @@ Message* MessageMap::find(SymbolString& master) for (unsigned char i=0; i::iterator it = m_passiveMessagesByKey.find(key); - if (it != m_passiveMessagesByKey.end()) + map::iterator it = m_messagesByKey.find(key); + if (it != m_messagesByKey.end()) return it->second; - if ((key & sourceMask) != 0) { - key &= ~sourceMask; // try again without specific source master - it = m_passiveMessagesByKey.find(key); - if (it != m_passiveMessagesByKey.end()) + if ((key & ID_SOURCE_MASK) != 0) { + it = m_messagesByKey.find(key & ~ID_SOURCE_MASK); // try again without specific source master + if (it != m_messagesByKey.end()) return it->second; } + + it = m_messagesByKey.find(key | ID_SOURCE_MASK); // try again with special value for active + if (it != m_messagesByKey.end()) + return it->second; } return NULL; @@ -505,7 +511,7 @@ void MessageMap::clear() m_messageCount = 0; m_messagesByName.clear(); // clear messages by key - m_passiveMessagesByKey.clear(); + m_messagesByKey.clear(); m_minIdLength = 4; m_maxIdLength = 0; } diff --git a/src/lib/ebus/message.h b/src/lib/ebus/message.h index 938ca4d0..fd070295 100644 --- a/src/lib/ebus/message.h +++ b/src/lib/ebus/message.h @@ -144,8 +144,8 @@ public: vector getId() const { return m_id; } /** - * @brief Return the key for storing in @a MessageSet. - * @return the key for storing in @a MessageSet. + * @brief Return the key for storing in @a MessageMap. + * @return the key for storing in @a MessageMap. */ unsigned long long getKey() { return m_key; } @@ -244,7 +244,7 @@ private: /** the primary, secondary, and optionally further command ID bytes. */ vector m_id; - /** the key for storing in @a MessageSet. */ + /** the key for storing in @a MessageMap. */ unsigned long long m_key; /** the @a DataField for encoding/decoding the message. */ @@ -292,7 +292,8 @@ public: /** * @brief Construct a new instance. */ - MessageMap() : FileReader::FileReader(true), m_minIdLength(4), m_maxIdLength(0), m_messageCount(0) {} + MessageMap() : FileReader::FileReader(true), + m_minIdLength(4), m_maxIdLength(0), m_messageCount(0), m_passiveMessageCount(0) {} /** * @brief Destructor. @@ -350,13 +351,13 @@ public: * @param passiveOnly true to count only passive messages, false to count all messages. * @return the the number of stored @a Message instances. */ - int size(const bool passiveOnly=false) { return passiveOnly ? m_passiveMessagesByKey.size() : m_messageCount; } + size_t size(const bool passiveOnly=false) { return passiveOnly ? m_passiveMessageCount : m_messageCount; } /** * @brief Get the number of stored @a Message instances with a poll priority. * @return the the number of stored @a Message instances with a poll priority. */ - int sizePoll() { return m_pollMessages.size(); } + size_t sizePoll() { return m_pollMessages.size(); } /** * @brief Get the next @a Message to poll. @@ -374,13 +375,16 @@ private: unsigned char m_maxIdLength; /** the number of distinct @a Message instances stored in @a m_messagesByName. */ - int m_messageCount; + size_t m_messageCount; + + /** the number of distinct passive @a Message instances stored in @a m_messagesByKey. */ + size_t m_passiveMessageCount; /** the known @a Message instances by class and name. */ map m_messagesByName; - /** the known passive @a Message instances by key. */ - map m_passiveMessagesByKey; + /** the known @a Message instances by key. */ + map m_messagesByKey; /** the known @a Message instances to poll, by priority. */ priority_queue, compareMessagePriority> m_pollMessages;