also calculate key for temporary message, keep initial leadingSeparator if it was passed true in decode() and decodeLastData(), use empty condition messagename for referencing scan result, added MessageMap::getScanMessage(), do not poll for scan message, store derived scan message by key only, removed unnecessary minIdLength determination
This commit is contained in:
+60
-42
@@ -36,8 +36,8 @@ using namespace std;
|
|||||||
/** the maximum poll priority for a @a Message referred to by a @a Condition. */
|
/** the maximum poll priority for a @a Message referred to by a @a Condition. */
|
||||||
#define POLL_PRIORITY_CONDITION 5
|
#define POLL_PRIORITY_CONDITION 5
|
||||||
|
|
||||||
Message::Message(const string circuit, const string name, const bool isWrite,
|
Message::Message(const string circuit, const string name,
|
||||||
const bool isPassive, const string comment,
|
const bool isWrite, const bool isPassive, const string comment,
|
||||||
const unsigned char srcAddress, const unsigned char dstAddress,
|
const unsigned char srcAddress, const unsigned char dstAddress,
|
||||||
const vector<unsigned char> id,
|
const vector<unsigned char> id,
|
||||||
DataField* data, const bool deleteData,
|
DataField* data, const bool deleteData,
|
||||||
@@ -76,7 +76,11 @@ Message::Message(const bool isWrite, const bool isPassive,
|
|||||||
{
|
{
|
||||||
m_id.push_back(pb);
|
m_id.push_back(pb);
|
||||||
m_id.push_back(sb);
|
m_id.push_back(sb);
|
||||||
m_key = 0;
|
unsigned long long key = (isPassive ? 0LL : 0x1fLL) << (8 * 7);
|
||||||
|
key |= (unsigned long long)SYN << (8 * 6);
|
||||||
|
key |= (unsigned long long)pb << (8 * 5);
|
||||||
|
key |= (unsigned long long)sb << (8 * 4);
|
||||||
|
m_key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -456,7 +460,7 @@ result_t Message::decode(SymbolString& masterData, SymbolString& slaveData,
|
|||||||
return result;
|
return result;
|
||||||
bool empty = result == RESULT_EMPTY;
|
bool empty = result == RESULT_EMPTY;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
leadingSeparator = output.str().length() > startPos;
|
leadingSeparator |= output.str().length() > startPos;
|
||||||
result = m_data->read(pt_slaveData, slaveData, offset, output, outputFormat, leadingSeparator, NULL, -1);
|
result = m_data->read(pt_slaveData, slaveData, offset, output, outputFormat, leadingSeparator, NULL, -1);
|
||||||
if (result < RESULT_OK)
|
if (result < RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -489,7 +493,7 @@ result_t Message::decodeLastData(ostringstream& output, OutputFormat outputForma
|
|||||||
return result;
|
return result;
|
||||||
bool empty = result == RESULT_EMPTY;
|
bool empty = result == RESULT_EMPTY;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
leadingSeparator = output.str().length() > startPos;
|
leadingSeparator |= output.str().length() > startPos;
|
||||||
result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, outputFormat, leadingSeparator, fieldName, fieldIndex);
|
result = m_data->read(pt_slaveData, m_lastSlaveData, offset, output, outputFormat, leadingSeparator, fieldName, fieldIndex);
|
||||||
if (result < RESULT_OK)
|
if (result < RESULT_OK)
|
||||||
return result;
|
return result;
|
||||||
@@ -655,11 +659,7 @@ result_t Condition::create(vector<string>::iterator& it, const vector<string>::i
|
|||||||
return RESULT_ERR_EOF;
|
return RESULT_ERR_EOF;
|
||||||
}
|
}
|
||||||
string circuit = *(it++); // circuit
|
string circuit = *(it++); // circuit
|
||||||
if (circuit.length()==0)
|
|
||||||
return RESULT_ERR_INVALID_ARG;
|
|
||||||
string name = it==end ? "" : *(it++); // messagename
|
string name = it==end ? "" : *(it++); // messagename
|
||||||
if (name.length()==0)
|
|
||||||
return RESULT_ERR_INVALID_ARG;
|
|
||||||
it++; // comment
|
it++; // comment
|
||||||
string field = it==end ? "" : *(it++); // fieldname
|
string field = it==end ? "" : *(it++); // fieldname
|
||||||
string zz = it==end ? "" : *(it++); // ZZ
|
string zz = it==end ? "" : *(it++); // ZZ
|
||||||
@@ -727,9 +727,14 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
|
|||||||
{
|
{
|
||||||
if (m_message!=NULL)
|
if (m_message!=NULL)
|
||||||
return RESULT_OK; // already resolved
|
return RESULT_OK; // already resolved
|
||||||
Message* message = messages->find(m_circuit, m_name, false);
|
Message* message;
|
||||||
if (!message)
|
if (m_name.length()==0) {
|
||||||
message = messages->find(m_circuit, m_name, false, true);
|
message = messages->getScanMessage(m_dstAddress);
|
||||||
|
} else {
|
||||||
|
message = messages->find(m_circuit, m_name, false);
|
||||||
|
if (!message)
|
||||||
|
message = messages->find(m_circuit, m_name, false, true);
|
||||||
|
}
|
||||||
if (!message) {
|
if (!message) {
|
||||||
errorMessage << "condition " << m_circuit << " " << m_name << ": message not found";
|
errorMessage << "condition " << m_circuit << " " << m_name << ": message not found";
|
||||||
return RESULT_ERR_NOTFOUND;
|
return RESULT_ERR_NOTFOUND;
|
||||||
@@ -766,7 +771,8 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
|
|||||||
}
|
}
|
||||||
m_message = message;
|
m_message = message;
|
||||||
message->setUsedByCondition();
|
message->setUsedByCondition();
|
||||||
messages->addPollMessage(message, true);
|
if (m_name.length()>0)
|
||||||
|
messages->addPollMessage(message, true);
|
||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -817,7 +823,7 @@ bool CombinedCondition::isTrue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
result_t MessageMap::add(Message* message)
|
result_t MessageMap::add(Message* message, bool storeByName)
|
||||||
{
|
{
|
||||||
unsigned long long key = message->getKey();
|
unsigned long long key = message->getKey();
|
||||||
bool conditional = message->isConditional();
|
bool conditional = message->isConditional();
|
||||||
@@ -832,40 +838,40 @@ result_t MessageMap::add(Message* message)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool isPassive = message->isPassive();
|
bool isPassive = message->isPassive();
|
||||||
bool isWrite = message->isWrite();
|
if (storeByName) {
|
||||||
string circuit = strtolower(message->getCircuit());
|
bool isWrite = message->isWrite();
|
||||||
string name = strtolower(message->getName());
|
string circuit = strtolower(message->getCircuit());
|
||||||
string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name;
|
string name = strtolower(message->getName());
|
||||||
if (!m_addAll) {
|
string nameKey = string(isPassive ? "P" : (isWrite ? "W" : "R")) + circuit + FIELD_SEPARATOR + name;
|
||||||
|
if (!m_addAll) {
|
||||||
|
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
|
||||||
|
if (nameIt != m_messagesByName.end()) {
|
||||||
|
vector<Message*>* messages = &nameIt->second;
|
||||||
|
if (!message->isConditional() || !messages->front()->isConditional())
|
||||||
|
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_messagesByName[nameKey].push_back(message);
|
||||||
|
|
||||||
|
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
|
||||||
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
|
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
|
||||||
if (nameIt != m_messagesByName.end()) {
|
if (nameIt == m_messagesByName.end())
|
||||||
|
m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name)
|
||||||
|
else {
|
||||||
vector<Message*>* messages = &nameIt->second;
|
vector<Message*>* messages = &nameIt->second;
|
||||||
if (!message->isConditional() || !messages->front()->isConditional())
|
Message* first = messages->front();
|
||||||
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
|
if (circuit < first->getCircuit())
|
||||||
|
m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name)
|
||||||
|
else if (m_addAll || (conditional && first->isConditional()))
|
||||||
|
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_messagesByName[nameKey].push_back(message);
|
|
||||||
m_messageCount++;
|
m_messageCount++;
|
||||||
if (conditional)
|
if (conditional)
|
||||||
m_conditionalMessageCount++;
|
m_conditionalMessageCount++;
|
||||||
if (isPassive)
|
if (isPassive)
|
||||||
m_passiveMessageCount++;
|
m_passiveMessageCount++;
|
||||||
|
|
||||||
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
|
|
||||||
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
|
|
||||||
if (nameIt == m_messagesByName.end())
|
|
||||||
m_messagesByName[nameKey].push_back(message); // always store first message without circuit (in order of circuit name)
|
|
||||||
else {
|
|
||||||
vector<Message*>* messages = &nameIt->second;
|
|
||||||
Message* first = messages->front();
|
|
||||||
if (circuit < first->getCircuit())
|
|
||||||
m_messagesByName[nameKey].at(0) = message; // always store first message without circuit (in order of circuit name)
|
|
||||||
else if (m_addAll || (conditional && first->isConditional()))
|
|
||||||
m_messagesByName[nameKey].push_back(message); // store further messages only if both are conditional or if storing everything
|
|
||||||
}
|
|
||||||
unsigned char idLength = (unsigned char)(message->getId().size() - 2);
|
unsigned char idLength = (unsigned char)(message->getId().size() - 2);
|
||||||
if (idLength < m_minIdLength)
|
|
||||||
m_minIdLength = idLength;
|
|
||||||
if (idLength > m_maxIdLength)
|
if (idLength > m_maxIdLength)
|
||||||
m_maxIdLength = idLength;
|
m_maxIdLength = idLength;
|
||||||
m_messagesByKey[key].push_back(message);
|
m_messagesByKey[key].push_back(message);
|
||||||
@@ -989,6 +995,21 @@ result_t MessageMap::addFromFile(vector<string>::iterator& begin, const vector<s
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Message* MessageMap::getScanMessage(const unsigned char dstAddress)
|
||||||
|
{
|
||||||
|
if (dstAddress==SYN)
|
||||||
|
return m_scanMessage;
|
||||||
|
if (!isValidAddress(dstAddress, false) || isMaster(dstAddress))
|
||||||
|
return NULL;
|
||||||
|
unsigned long long key = m_scanMessage->getDerivedKey(dstAddress);
|
||||||
|
vector<Message*>* msgs = getByKey(key);
|
||||||
|
if (msgs!=NULL)
|
||||||
|
return msgs->front();
|
||||||
|
Message* message = m_scanMessage->derive(dstAddress);
|
||||||
|
add(message, false);
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
result_t MessageMap::resolveConditions(bool verbose) {
|
result_t MessageMap::resolveConditions(bool verbose) {
|
||||||
result_t overallResult = RESULT_OK;
|
result_t overallResult = RESULT_OK;
|
||||||
for (map<string, Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
|
for (map<string, Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
|
||||||
@@ -1102,14 +1123,12 @@ deque<Message*> MessageMap::findAll(SymbolString& master)
|
|||||||
if (master.size() < 5)
|
if (master.size() < 5)
|
||||||
return ret;
|
return ret;
|
||||||
unsigned char maxIdLength = master[4];
|
unsigned char maxIdLength = master[4];
|
||||||
if (maxIdLength < m_minIdLength)
|
|
||||||
return ret;
|
|
||||||
if (maxIdLength > m_maxIdLength)
|
if (maxIdLength > m_maxIdLength)
|
||||||
maxIdLength = m_maxIdLength;
|
maxIdLength = m_maxIdLength;
|
||||||
if (master.size() < 5+maxIdLength)
|
if (master.size() < 5+maxIdLength)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
for (int idLength = maxIdLength; ret.size()==0 && idLength >= m_minIdLength; idLength--) {
|
for (int idLength = maxIdLength; ret.size()==0 && idLength >= 0; idLength--) {
|
||||||
int exp = 7;
|
int exp = 7;
|
||||||
unsigned long long key = (unsigned long long)idLength << (8 * exp + 5);
|
unsigned long long key = (unsigned long long)idLength << (8 * exp + 5);
|
||||||
key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--);
|
key |= (unsigned long long)getMasterNumber(master[0]) << (8 * exp--);
|
||||||
@@ -1207,7 +1226,6 @@ void MessageMap::clear()
|
|||||||
// clear messages by key
|
// clear messages by key
|
||||||
m_messagesByKey.clear();
|
m_messagesByKey.clear();
|
||||||
m_conditions.clear();
|
m_conditions.clear();
|
||||||
m_minIdLength = 4;
|
|
||||||
m_maxIdLength = 0;
|
m_maxIdLength = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+21
-10
@@ -60,8 +60,8 @@ public:
|
|||||||
* @param pollPriority the priority for polling, or 0 for no polling at all.
|
* @param pollPriority the priority for polling, or 0 for no polling at all.
|
||||||
* @param condition the @a Condition for this message, or NULL.
|
* @param condition the @a Condition for this message, or NULL.
|
||||||
*/
|
*/
|
||||||
Message(const string circuit, const string name, const bool isWrite,
|
Message(const string circuit, const string name,
|
||||||
const bool isPassive, const string comment,
|
const bool isWrite, const bool isPassive, const string comment,
|
||||||
const unsigned char srcAddress, const unsigned char dstAddress,
|
const unsigned char srcAddress, const unsigned char dstAddress,
|
||||||
const vector<unsigned char> id,
|
const vector<unsigned char> id,
|
||||||
DataField* data, const bool deleteData,
|
DataField* data, const bool deleteData,
|
||||||
@@ -502,8 +502,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Construct a new instance.
|
* Construct a new instance.
|
||||||
* @param circuit the circuit name.
|
* @param circuit the circuit name.
|
||||||
* @param name the message name.
|
* @param name the message name, or empty for scan message.
|
||||||
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination).
|
* @param dstAddress the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message).
|
||||||
* @param field the field name.
|
* @param field the field name.
|
||||||
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
|
* @param valueRanges the valid value ranges (pairs of from/to inclusive), empty for @a m_message seen check.
|
||||||
*/
|
*/
|
||||||
@@ -539,10 +539,10 @@ private:
|
|||||||
/** the circuit name. */
|
/** the circuit name. */
|
||||||
const string m_circuit;
|
const string m_circuit;
|
||||||
|
|
||||||
/** the message name. */
|
/** the message name, or empty for scan message. */
|
||||||
const string m_name;
|
const string m_name;
|
||||||
|
|
||||||
/** the override destination address, or @a SYN (only for @a Message without specific destination). */
|
/** the override destination address, or @a SYN (only for @a Message without specific destination as well as scan message). */
|
||||||
const unsigned char m_dstAddress;
|
const unsigned char m_dstAddress;
|
||||||
|
|
||||||
/** the field name, or empty for first field. */
|
/** the field name, or empty for first field. */
|
||||||
@@ -604,7 +604,10 @@ public:
|
|||||||
* @param addAll whether to add all messages, even if duplicate.
|
* @param addAll whether to add all messages, even if duplicate.
|
||||||
*/
|
*/
|
||||||
MessageMap(const bool addAll=false) : FileReader<DataFieldTemplates*>::FileReader(true),
|
MessageMap(const bool addAll=false) : FileReader<DataFieldTemplates*>::FileReader(true),
|
||||||
m_addAll(addAll), m_minIdLength(4), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0) {}
|
m_addAll(addAll), m_maxIdLength(0), m_messageCount(0), m_conditionalMessageCount(0), m_passiveMessageCount(0)
|
||||||
|
{
|
||||||
|
m_scanMessage = new Message(false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Destructor.
|
* Destructor.
|
||||||
@@ -614,10 +617,11 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Add a @a Message instance to this set.
|
* Add a @a Message instance to this set.
|
||||||
* @param message the @a Message instance to add.
|
* @param message the @a Message instance to add.
|
||||||
|
* @param storeByName whether to store the @a Message by name.
|
||||||
* @return @a RESULT_OK on success, or an error code.
|
* @return @a RESULT_OK on success, or an error code.
|
||||||
* Note: the caller may not free the added instance on success.
|
* Note: the caller may not free the added instance on success.
|
||||||
*/
|
*/
|
||||||
result_t add(Message* message);
|
result_t add(Message* message, bool storeByName=true);
|
||||||
|
|
||||||
// @copydoc
|
// @copydoc
|
||||||
virtual result_t addDefaultFromFile(vector< vector<string> >& defaults, vector<string>& row,
|
virtual result_t addDefaultFromFile(vector< vector<string> >& defaults, vector<string>& row,
|
||||||
@@ -638,6 +642,13 @@ public:
|
|||||||
DataFieldTemplates* arg, vector< vector<string> >* defaults,
|
DataFieldTemplates* arg, vector< vector<string> >* defaults,
|
||||||
const string& filename, unsigned int lineNo);
|
const string& filename, unsigned int lineNo);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the scan @a Message instance for the specified address.
|
||||||
|
* @param dstAddress the destination address, or @a SYN for the base scan @a Message.
|
||||||
|
* @return the scan @a Message instance, or NULL if the dstAddress is no slave.
|
||||||
|
*/
|
||||||
|
Message* getScanMessage(const unsigned char dstAddress=SYN);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve all @a Condition instances.
|
* Resolve all @a Condition instances.
|
||||||
* @param verbose whether to verbosely add all problems to the error message.
|
* @param verbose whether to verbosely add all problems to the error message.
|
||||||
@@ -767,8 +778,8 @@ private:
|
|||||||
/** whether to add all messages, even if duplicate. */
|
/** whether to add all messages, even if duplicate. */
|
||||||
const bool m_addAll;
|
const bool m_addAll;
|
||||||
|
|
||||||
/** the minimum ID length used by any of the known @a Message instances. */
|
/** the @a Message instance used for scanning. */
|
||||||
unsigned char m_minIdLength;
|
Message* m_scanMessage;
|
||||||
|
|
||||||
/** the maximum ID length used by any of the known @a Message instances. */
|
/** the maximum ID length used by any of the known @a Message instances. */
|
||||||
unsigned char m_maxIdLength;
|
unsigned char m_maxIdLength;
|
||||||
|
|||||||
Reference in New Issue
Block a user