separate access level from circuit, introduce type for columns

This commit is contained in:
john30
2017-02-18 11:43:42 +01:00
parent de66ead9a6
commit 515f412113
3 changed files with 200 additions and 107 deletions
+110 -62
View File
@@ -58,14 +58,14 @@ using std::setw;
extern DataFieldTemplates* getTemplates(const string filename); extern DataFieldTemplates* getTemplates(const string filename);
Message::Message(const string circuit, const string name, Message::Message(const string circuit, const string level, const string name,
const bool isWrite, 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,
const unsigned char pollPriority, const unsigned char pollPriority,
Condition* condition) Condition* condition)
: m_circuit(circuit), m_name(name), m_isWrite(isWrite), : m_circuit(circuit), m_level(level), m_name(name), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(comment), m_isPassive(isPassive), m_comment(comment),
m_srcAddress(srcAddress), m_dstAddress(dstAddress), m_srcAddress(srcAddress), m_dstAddress(dstAddress),
m_id(id), m_data(data), m_deleteData(deleteData), m_id(id), m_data(data), m_deleteData(deleteData),
@@ -79,14 +79,17 @@ Message::Message(const string circuit, const string name,
} }
} }
Message::Message(const string circuit, const string name, Message::Message(const string circuit, const string level, const string name,
const bool isWrite, const bool isPassive, const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, const bool deleteData) DataField* data, const bool deleteData)
: m_circuit(circuit), m_name(name), m_isWrite(isWrite), m_isPassive(isPassive), m_comment(), m_srcAddress(SYN), : m_circuit(circuit), m_level(level), m_name(name), m_isWrite(isWrite),
m_dstAddress(SYN), m_data(data), m_deleteData(true), m_pollPriority(0), m_usedByCondition(false), m_isPassive(isPassive), m_comment(),
m_isScanMessage(false), m_condition(NULL), m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_srcAddress(SYN), m_dstAddress(SYN),
m_lastPollTime(0) { m_data(data), m_deleteData(true),
m_pollPriority(0),
m_usedByCondition(false), m_isScanMessage(false), m_condition(NULL),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
m_id.push_back(pb); m_id.push_back(pb);
m_id.push_back(sb); m_id.push_back(sb);
uint64_t key = 0; uint64_t key = 0;
@@ -253,10 +256,16 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
} }
string circuit = getDefault(*it++, defaults, defaultPos++, true); // [circuit] string circuit = getDefault(*it++, defaults, defaultPos++, true); // [circuit[#level]]
if (it == end) { if (it == end) {
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
} }
string level;
size_t pos = circuit.find('#');
if (pos != string::npos) {
level = circuit.substr(pos+1);
circuit.resize(pos);
}
string name = getDefault(*it++, defaults, defaultPos++, true, true); // name string name = getDefault(*it++, defaults, defaultPos++, true, true); // name
if (it == end) { if (it == end) {
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
@@ -453,10 +462,10 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
Message* message; Message* message;
if (chainIds.size() > 1) { if (chainIds.size() > 1) {
message = new ChainedMessage(useCircuit, name, isWrite, comment, srcAddress, dstAddress, id, chainIds, message = new ChainedMessage(useCircuit, level, name, isWrite, comment, srcAddress, dstAddress, id, chainIds,
chainLengths, data, index == 0, pollPriority, condition); chainLengths, data, index == 0, pollPriority, condition);
} else { } else {
message = new Message(useCircuit, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, message = new Message(useCircuit, level, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data,
index == 0, pollPriority, condition); index == 0, pollPriority, condition);
} }
messages.push_back(message); messages.push_back(message);
@@ -465,11 +474,11 @@ result_t Message::create(vector<string>::iterator& it, const vector<string>::ite
} }
Message* Message::createScanMessage() { Message* Message::createScanMessage() {
return new Message("scan", "", false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true); return new Message("scan", "", "", false, false, 0x07, 0x04, DataFieldSet::getIdentFields(), true);
} }
Message* Message::derive(const unsigned char dstAddress, const unsigned char srcAddress, const string circuit) { Message* Message::derive(const unsigned char dstAddress, const unsigned char srcAddress, const string circuit) {
Message* result = new Message(circuit.length() == 0 ? m_circuit : circuit, m_name, Message* result = new Message(circuit.length() == 0 ? m_circuit : circuit, m_level, m_name,
m_isWrite, m_isPassive, m_comment, m_isWrite, m_isPassive, m_comment,
srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress, srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_data, false, m_id, m_data, false,
@@ -489,6 +498,28 @@ Message* Message::derive(const unsigned char dstAddress, const bool extendCircui
return derive(dstAddress, SYN, m_circuit); return derive(dstAddress, SYN, m_circuit);
} }
bool Message::checkLevel(const string level, const string checkLevels) {
if (level.empty()) {
return true;
}
if (checkLevels.empty()) {
return false;
}
if (checkLevels == "*") {
return true;
}
size_t len = level.length();
size_t maxLen = checkLevels.length();
for (size_t pos = checkLevels.find(level); pos != string::npos && pos + len <= maxLen;
pos = checkLevels.find(level, pos)) {
if ((pos == 0 || checkLevels[pos - 1] == VALUE_SEPARATOR)
&& (pos + len == maxLen || checkLevels[pos + len] == VALUE_SEPARATOR)) {
return true;
}
pos += len;
}
return false;
}
bool Message::checkIdPrefix(vector<unsigned char>& id) { bool Message::checkIdPrefix(vector<unsigned char>& id) {
if (id.size() > m_id.size()) { if (id.size() > m_id.size()) {
return false; return false;
@@ -765,23 +796,35 @@ bool Message::isLessPollWeight(const Message* other) {
return false; return false;
} }
void Message::dump(ostream& output, vector<size_t>* columns, bool withConditions) { void Message::dump(ostream& output, vector<column_t>* columns, bool withConditions) {
bool first = true, all = columns == NULL; bool first = true;
size_t end = all ? 9 : columns->size(); if (columns == NULL) {
for (size_t i = 0; i < end; i++) { for (int column = COLUMN_FIRST; column != COLUMN_LAST; column++) {
if (column == COLUMN_LEVEL) {
continue; // access level not included in default dump format
}
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
dumpColumn(output, static_cast<column_t>(column), withConditions);
}
return;
}
for (auto column : *columns) {
if (first) { if (first) {
first = false; first = false;
} else { } else {
output << FIELD_SEPARATOR; output << FIELD_SEPARATOR;
} }
size_t column = all ? i : (*columns)[i];
dumpColumn(output, column, withConditions); dumpColumn(output, column, withConditions);
} }
} }
void Message::dumpColumn(ostream& output, size_t column, bool withConditions) { void Message::dumpColumn(ostream& output, column_t column, bool withConditions) {
switch (column) { switch (column) {
case COLUMN_TYPE: // type case COLUMN_TYPE:
if (withConditions && m_condition != NULL) { if (withConditions && m_condition != NULL) {
m_condition->dump(output); m_condition->dump(output);
} }
@@ -799,43 +842,49 @@ void Message::dumpColumn(ostream& output, size_t column, bool withConditions) {
} }
} }
break; break;
case COLUMN_CIRCUIT: // circuit case COLUMN_CIRCUIT:
DataField::dumpString(output, m_circuit, false); DataField::dumpString(output, m_circuit, false);
break; break;
case COLUMN_NAME: // name case COLUMN_LEVEL:
DataField::dumpString(output, m_level, false);
break;
case COLUMN_NAME:
DataField::dumpString(output, m_name, false); DataField::dumpString(output, m_name, false);
break; break;
case COLUMN_COMMENT: // comment case COLUMN_COMMENT:
DataField::dumpString(output, m_comment, false); DataField::dumpString(output, m_comment, false);
break; break;
case COLUMN_QQ: // QQ case COLUMN_QQ:
if (m_srcAddress != SYN) { if (m_srcAddress != SYN) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_srcAddress); output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_srcAddress);
} }
break; break;
case COLUMN_ZZ: // ZZ case COLUMN_ZZ:
if (m_dstAddress != SYN) { if (m_dstAddress != SYN) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress); output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress);
} }
break; break;
case COLUMN_PBSB: // PBSB case COLUMN_PBSB:
for (vector<unsigned char>::const_iterator it = m_id.begin(); it < m_id.begin()+2 && it < m_id.end(); it++) { for (vector<unsigned char>::const_iterator it = m_id.begin(); it < m_id.begin()+2 && it < m_id.end(); it++) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it); output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it);
} }
break; break;
case COLUMN_ID: // ID case COLUMN_ID:
for (vector<unsigned char>::const_iterator it = m_id.begin()+2; it < m_id.end(); it++) { for (vector<unsigned char>::const_iterator it = m_id.begin()+2; it < m_id.end(); it++) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it); output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it);
} }
break; break;
case COLUMN_FIELDS: // fields case COLUMN_FIELDS:
m_data->dump(output); m_data->dump(output);
break; break;
case COLUMN_LAST:
default:
break;
} }
} }
ChainedMessage::ChainedMessage(const string circuit, const string name, ChainedMessage::ChainedMessage(const string circuit, const string level, const string name,
const bool isWrite, const string comment, const bool isWrite, 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,
@@ -843,7 +892,7 @@ ChainedMessage::ChainedMessage(const string circuit, const string name,
DataField* data, const bool deleteData, DataField* data, const bool deleteData,
const unsigned char pollPriority, const unsigned char pollPriority,
Condition* condition) Condition* condition)
: Message(circuit, name, isWrite, false, comment, : Message(circuit, level, name, isWrite, false, comment,
srcAddress, dstAddress, id, srcAddress, dstAddress, id,
data, deleteData, pollPriority, condition), data, deleteData, pollPriority, condition),
m_ids(ids), m_lengths(lengths), m_ids(ids), m_lengths(lengths),
@@ -873,7 +922,7 @@ ChainedMessage::~ChainedMessage() {
} }
Message* ChainedMessage::derive(const unsigned char dstAddress, const unsigned char srcAddress, const string circuit) { Message* ChainedMessage::derive(const unsigned char dstAddress, const unsigned char srcAddress, const string circuit) {
ChainedMessage* result = new ChainedMessage(circuit.length() == 0 ? m_circuit : circuit, m_name, ChainedMessage* result = new ChainedMessage(circuit.length() == 0 ? m_circuit : circuit, m_level, m_name,
m_isWrite, m_comment, m_isWrite, m_comment,
srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress, srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_ids, m_lengths, m_data, false, m_id, m_ids, m_lengths, m_data, false,
@@ -1077,7 +1126,7 @@ result_t ChainedMessage::storeLastData(const PartType partType, SymbolString& da
return result; return result;
} }
void ChainedMessage::dumpColumn(ostream& output, size_t column, bool withConditions) { void ChainedMessage::dumpColumn(ostream& output, column_t column, bool withConditions) {
if (column != COLUMN_ID) { if (column != COLUMN_ID) {
Message::dumpColumn(output, column, withConditions); Message::dumpColumn(output, column, withConditions);
return; return;
@@ -1211,7 +1260,13 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end, result_t Condition::create(const string condName, vector<string>::iterator& it, const vector<string>::iterator end,
string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) { string defaultDest, string defaultCircuit, SimpleCondition*& returnValue) {
// name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller) // name,circuit,messagename,[comment],[fieldname],[ZZ],values (name already skipped by caller)
string circuit = it == end ? "" : *(it++); // circuit string circuit = it == end ? "" : *(it++); // circuit[#level]
string level;
size_t pos = circuit.find('#');
if (pos != string::npos) {
level = circuit.substr(pos+1);
circuit.resize(pos);
}
string name = it == end ? "" : *(it++); // messagename string name = it == end ? "" : *(it++); // messagename
if (it < end) { if (it < end) {
it++; // comment it++; // comment
@@ -1241,7 +1296,7 @@ result_t Condition::create(const string condName, vector<string>::iterator& it,
} }
string valueList = it == end ? "" : *(it++); string valueList = it == end ? "" : *(it++);
if (valueList.length() == 0) { if (valueList.length() == 0) {
returnValue = new SimpleCondition(condName, condName, circuit, name, dstAddress, field); returnValue = new SimpleCondition(condName, condName, circuit, level, name, dstAddress, field);
return RESULT_OK; return RESULT_OK;
} }
if (valueList[0] == '\'') { if (valueList[0] == '\'') {
@@ -1251,7 +1306,7 @@ result_t Condition::create(const string condName, vector<string>::iterator& it,
if (result != RESULT_OK) { if (result != RESULT_OK) {
return result; return result;
} }
returnValue = new SimpleStringCondition(condName, condName, circuit, name, dstAddress, field, values); returnValue = new SimpleStringCondition(condName, condName, circuit, level, name, dstAddress, field, values);
return RESULT_OK; return RESULT_OK;
} }
// numbers // numbers
@@ -1260,7 +1315,7 @@ result_t Condition::create(const string condName, vector<string>::iterator& it,
if (result != RESULT_OK) { if (result != RESULT_OK) {
return result; return result;
} }
returnValue = new SimpleNumericCondition(condName, condName, circuit, name, dstAddress, field, valueRanges); returnValue = new SimpleNumericCondition(condName, condName, circuit, level, name, dstAddress, field, valueRanges);
return RESULT_OK; return RESULT_OK;
} }
@@ -1280,7 +1335,7 @@ SimpleCondition* SimpleCondition::derive(string valueList) {
if (result != RESULT_OK) { if (result != RESULT_OK) {
return NULL; return NULL;
} }
return new SimpleStringCondition(name, m_refName, m_circuit, m_name, m_dstAddress, m_field, values); return new SimpleStringCondition(name, m_refName, m_circuit, m_level, m_name, m_dstAddress, m_field, values);
} }
// numbers // numbers
if (!isNumeric()) { if (!isNumeric()) {
@@ -1291,7 +1346,7 @@ SimpleCondition* SimpleCondition::derive(string valueList) {
if (result != RESULT_OK) { if (result != RESULT_OK) {
return NULL; return NULL;
} }
return new SimpleNumericCondition(name, m_refName, m_circuit, m_name, m_dstAddress, m_field, valueRanges); return new SimpleNumericCondition(name, m_refName, m_circuit, m_level, m_name, m_dstAddress, m_field, valueRanges);
} }
void SimpleCondition::dump(ostream& output, bool matched) { void SimpleCondition::dump(ostream& output, bool matched) {
@@ -1323,9 +1378,9 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0') errorMessage << "scan condition " << nouppercase << setw(2) << hex << setfill('0')
<< static_cast<unsigned>(m_dstAddress); << static_cast<unsigned>(m_dstAddress);
} else { } else {
message = messages->find(m_circuit, m_name, false); message = messages->find(m_circuit, m_name, m_level, false);
if (!message) { if (!message) {
message = messages->find(m_circuit, m_name, false, true); message = messages->find(m_circuit, m_name, m_level, false, true);
} }
errorMessage << "condition " << m_circuit << " " << m_name; errorMessage << "condition " << m_circuit << " " << m_name;
} }
@@ -1639,7 +1694,7 @@ result_t MessageMap::addDefaultFromFile(vector< vector<string> >& defaults, vect
if (row[1].length() == 0) { if (row[1].length() == 0) {
row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]" row[1] = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
} else if (row[1][0] == '#') { } else if (row[1][0] == '#') {
// move security suffix behind default circuit and suffix: "circuit[.suffix]#security" // move access level behind default circuit and suffix: "circuit[.suffix]#level"
row[1] = defaultCircuit+defaultSuffix+row[1]; row[1] = defaultCircuit+defaultSuffix+row[1];
} else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) { } else if (defaultSuffix.length() > 0 && row[1].find_last_of('.') == string::npos) {
// circuit suffix not yet present // circuit suffix not yet present
@@ -1647,7 +1702,7 @@ result_t MessageMap::addDefaultFromFile(vector< vector<string> >& defaults, vect
if (pos == string::npos) { if (pos == string::npos) {
row[1] += defaultSuffix; // append default suffix: "circuit.suffix" row[1] += defaultSuffix; // append default suffix: "circuit.suffix"
} else { } else {
// insert default suffix: "circuit.suffix#security" // insert default suffix: "circuit.suffix#level"
row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos); row[1] = row[1].substr(0, pos)+defaultSuffix+row[1].substr(pos);
} }
} }
@@ -1920,7 +1975,8 @@ vector<Message*>* MessageMap::getByKey(const uint64_t key) {
return NULL; return NULL;
} }
Message* MessageMap::find(const string& circuit, const string& name, const bool isWrite, const bool isPassive) { Message* MessageMap::find(const string& circuit, const string& levels, const string& name, const bool isWrite,
const bool isPassive) {
string lcircuit = circuit; string lcircuit = circuit;
FileReader::tolower(lcircuit); FileReader::tolower(lcircuit);
string lname = name; string lname = name;
@@ -1937,7 +1993,7 @@ Message* MessageMap::find(const string& circuit, const string& name, const bool
map<string, vector<Message*> >::iterator it = m_messagesByName.find(key); map<string, vector<Message*> >::iterator it = m_messagesByName.find(key);
if (it != m_messagesByName.end()) { if (it != m_messagesByName.end()) {
Message* message = getFirstAvailable(it->second); Message* message = getFirstAvailable(it->second);
if (message) { if (message && message->hasLevel(levels)) {
return message; return message;
} }
} }
@@ -1945,39 +2001,31 @@ Message* MessageMap::find(const string& circuit, const string& name, const bool
return NULL; return NULL;
} }
deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const bool completeMatch, deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const string& levels,
const bool withRead, const bool withWrite, const bool withPassive, const bool completeMatch, const bool withRead, const bool withWrite,
const bool completeMatchIgnoreCircuitSuffix, const bool onlyAvailable, const bool withPassive, const bool onlyAvailable,
const time_t since, const time_t until) { const time_t since, const time_t until) {
bool checkCircuitIgnoreSuffix = completeMatch && completeMatchIgnoreCircuitSuffix;
deque<Message*> ret; deque<Message*> ret;
string lcircuit = circuit; string lcircuit = circuit;
FileReader::tolower(lcircuit); FileReader::tolower(lcircuit);
string lname = name; string lname = name;
FileReader::tolower(lname); FileReader::tolower(lname);
bool checkCircuit = lcircuit.length() > 0; bool checkCircuit = lcircuit.length() > 0;
bool checkName = name.length() > 0; bool checkLevel = levels != "*";
if (checkCircuit && checkCircuitIgnoreSuffix) { bool includeEmptyLevel = levels.empty();
size_t pos = lcircuit.find('#'); bool checkName = lname.length() > 0;
if (pos != string::npos) {
lcircuit.resize(pos);
}
}
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) { for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
if (it->first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-" if (it->first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-"
continue; continue;
} }
for (vector<Message*>::iterator msgIt = it->second.begin(); msgIt != it->second.end(); msgIt++) { for (vector<Message*>::iterator msgIt = it->second.begin(); msgIt != it->second.end(); msgIt++) {
Message* message = *msgIt; Message* message = *msgIt;
if (checkLevel && !message->hasLevel(levels, includeEmptyLevel)) {
continue;
}
if (checkCircuit) { if (checkCircuit) {
string check = message->getCircuit(); string check = message->getCircuit();
FileReader::tolower(check); FileReader::tolower(check);
if (checkCircuitIgnoreSuffix) {
size_t pos = check.find('#');
if (pos != string::npos) {
check.resize(pos);
}
}
if (completeMatch ? (check != lcircuit) : (check.find(lcircuit) == check.npos)) { if (completeMatch ? (check != lcircuit) : (check.find(lcircuit) == check.npos)) {
continue; continue;
} }
@@ -2100,7 +2148,7 @@ void MessageMap::invalidateCache(Message* message) {
message->m_lastUpdateTime = 0; message->m_lastUpdateTime = 0;
string circuit = message->getCircuit(); string circuit = message->getCircuit();
string name = message->getName(); string name = message->getName();
deque<Message*> messages = findAll(circuit, name, true, true, true, true, true); deque<Message*> messages = findAll(circuit, name, "*", true, true, true, true);
for (deque<Message*>::iterator it = messages.begin(); it != messages.end(); it++) { for (deque<Message*>::iterator it = messages.begin(); it != messages.end(); it++) {
Message* checkMessage = *it; Message* checkMessage = *it;
if (checkMessage != message) { if (checkMessage != message) {
+89 -44
View File
@@ -68,32 +68,37 @@ class SimpleCondition;
class CombinedCondition; class CombinedCondition;
class MessageMap; class MessageMap;
/** the column index in @a Message::dump() for the message type. */ /**
#define COLUMN_TYPE 0 * Column type enumeration for CSV.
*/
enum column_t {
/** the column index in @a Message::dump() for the message type. */
COLUMN_TYPE,
/** the column index in @a Message::dump() for the circuit name. */
COLUMN_CIRCUIT,
/** the column index in @a Message::dump() for the access level. */
COLUMN_LEVEL,
/** the column index in @a Message::dump() for the message name. */
COLUMN_NAME,
/** the column index in @a Message::dump() for the message comment. */
COLUMN_COMMENT,
/** the column index in @a Message::dump() for the source address QQ. */
COLUMN_QQ,
/** the column index in @a Message::dump() for the destination address QQ. */
COLUMN_ZZ,
/** the column index in @a Message::dump() for the PBSB bytes. */
COLUMN_PBSB,
/** the column index in @a Message::dump() for the ID columns (after the PBSB bytes). */
COLUMN_ID,
/** the column index in @a Message::dump() for the field(s). */
COLUMN_FIELDS,
/** the marker column index for the next-to-last element. */
COLUMN_LAST,
};
/** the column index in @a Message::dump() for the circuit name. */ /** A link to the first column of @a column_t. */
#define COLUMN_CIRCUIT 1 #define COLUMN_FIRST COLUMN_TYPE
/** the column index in @a Message::dump() for the message name. */
#define COLUMN_NAME 2
/** the column index in @a Message::dump() for the message comment. */
#define COLUMN_COMMENT 3
/** the column index in @a Message::dump() for the source address QQ. */
#define COLUMN_QQ 4
/** the column index in @a Message::dump() for the destination address QQ. */
#define COLUMN_ZZ 5
/** the column index in @a Message::dump() for the PBSB bytes. */
#define COLUMN_PBSB 6
/** the column index in @a Message::dump() for the ID columns (after the PBSB bytes). */
#define COLUMN_ID 7
/** the column index in @a Message::dump() for the field(s). */
#define COLUMN_FIELDS 8
/** /**
* Defines parameters of a message sent or received on the bus. * Defines parameters of a message sent or received on the bus.
@@ -104,6 +109,7 @@ class Message {
/** /**
* Construct a new instance. * Construct a new instance.
* @param circuit the optional circuit name. * @param circuit the optional circuit name.
* @param level the optional access level.
* @param name the message name (unique within the same circuit and type). * @param name the message name (unique within the same circuit and type).
* @param isWrite whether this is a write message. * @param isWrite whether this is a write message.
* @param isPassive true if message can only be initiated by a participant other than us, * @param isPassive true if message can only be initiated by a participant other than us,
@@ -117,7 +123,7 @@ class Message {
* @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, Message(const string circuit, const string level, const string name,
const bool isWrite, 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,
@@ -130,6 +136,7 @@ class Message {
/** /**
* Construct a new scan @a Message instance. * Construct a new scan @a Message instance.
* @param circuit the circuit name, or empty for not storing by name. * @param circuit the circuit name, or empty for not storing by name.
* @param level the optional access level.
* @param name the message name (unique within the same circuit and type), or empty for not storing by name. * @param name the message name (unique within the same circuit and type), or empty for not storing by name.
* @param isWrite whether this is a write message. * @param isWrite whether this is a write message.
* @param isPassive true if message can only be initiated by a participant other than us, * @param isPassive true if message can only be initiated by a participant other than us,
@@ -139,7 +146,7 @@ class Message {
* @param data the @a DataField for encoding/decoding the message. * @param data the @a DataField for encoding/decoding the message.
* @param deleteData whether to delete the @a DataField during destruction. * @param deleteData whether to delete the @a DataField during destruction.
*/ */
Message(const string circuit, const string name, Message(const string circuit, const string level, const string name,
const bool isWrite, const bool isPassive, const bool isWrite, const bool isPassive,
const unsigned char pb, const unsigned char sb, const unsigned char pb, const unsigned char sb,
DataField* data, const bool deleteData); DataField* data, const bool deleteData);
@@ -246,6 +253,31 @@ class Message {
*/ */
string getCircuit() const { return m_circuit; } string getCircuit() const { return m_circuit; }
/**
* Get the optional access level.
* @return the optional access level.
*/
string getLevel() const { return m_level; }
/**
* Return whether one of the specified access levels allows access to this message.
* @param levels the allowed access levels to check, separated by semicolon.
* @param includeEmpty true to also allow this message when the message level is empty but does not match the
* level to check.
* @return true when access is granted.
*/
bool hasLevel(const string levels, bool includeEmpty = true) {
return m_level.empty() ? (includeEmpty || levels.empty()) : checkLevel(m_level, levels);
}
/**
* Check if the access level is part of the levels.
* @param level the access level to check.
* @param checkLevels the access levels to check against, separated by semicolon.
* @return whether the access level matches.
*/
static bool checkLevel(const string level, const string checkLevels);
/** /**
* Get the message name (unique within the same circuit and type). * Get the message name (unique within the same circuit and type).
* @return the message name (unique within the same circuit and type). * @return the message name (unique within the same circuit and type).
@@ -517,7 +549,7 @@ class Message {
* @param columns the list of column indexes to write, or NULL for all (see @p COLUMN_TYPE index constants). * @param columns the list of column indexes to write, or NULL for all (see @p COLUMN_TYPE index constants).
* @param withConditions whether to include the optional conditions prefix. * @param withConditions whether to include the optional conditions prefix.
*/ */
void dump(ostream& output, vector<size_t>* columns = NULL, bool withConditions = false); void dump(ostream& output, vector<column_t>* columns = NULL, bool withConditions = false);
/** /**
* Write the specified column to the @a ostream. * Write the specified column to the @a ostream.
@@ -525,13 +557,16 @@ class Message {
* @param column the column index to write (see @p COLUMN_TYPE index constants). * @param column the column index to write (see @p COLUMN_TYPE index constants).
* @param withConditions whether to include the optional conditions prefix. * @param withConditions whether to include the optional conditions prefix.
*/ */
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false); virtual void dumpColumn(ostream& output, column_t column, bool withConditions = false);
protected: protected:
/** the optional circuit name. */ /** the optional circuit name. */
const string m_circuit; const string m_circuit;
/** the optional access level. */
const string m_level;
/** the message name (unique within the same circuit and type). */ /** the message name (unique within the same circuit and type). */
const string m_name; const string m_name;
@@ -623,6 +658,7 @@ class ChainedMessage : public Message {
/** /**
* Construct a new instance. * Construct a new instance.
* @param circuit the optional circuit name. * @param circuit the optional circuit name.
* @param level the optional access level.
* @param name the message name (unique within the same circuit and type). * @param name the message name (unique within the same circuit and type).
* @param isWrite whether this is a write message. * @param isWrite whether this is a write message.
* @param comment the comment. * @param comment the comment.
@@ -636,7 +672,7 @@ class ChainedMessage : public Message {
* @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.
*/ */
ChainedMessage(const string circuit, const string name, ChainedMessage(const string circuit, const string level, const string name,
const bool isWrite, const string comment, const bool isWrite, 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,
@@ -679,7 +715,7 @@ class ChainedMessage : public Message {
protected: protected:
// @copydoc // @copydoc
virtual void dumpColumn(ostream& output, size_t column, bool withConditions = false); virtual void dumpColumn(ostream& output, column_t column, bool withConditions = false);
private: private:
@@ -828,17 +864,18 @@ class SimpleCondition : public Condition {
* @param condName the name of the condition. * @param condName the name of the condition.
* @param refName the reference name for dumping. * @param refName the reference name for dumping.
* @param circuit the circuit name. * @param circuit the circuit name.
* @param level the access level.
* @param name the message name, or empty for scan message. * @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). * as well as scan message).
* @param field the field name. * @param field the field name.
* @param hasValues whether a value has to be checked against. * @param hasValues whether a value has to be checked against.
*/ */
SimpleCondition(const string condName, const string refName, const string circuit, const string name, SimpleCondition(const string condName, const string refName, const string circuit, const string level,
const unsigned char dstAddress, const string field, const bool hasValues = false) const string name, const unsigned char dstAddress, const string field, const bool hasValues = false)
: Condition(), : Condition(),
m_condName(condName), m_refName(refName), m_circuit(circuit), m_name(name), m_dstAddress(dstAddress), m_condName(condName), m_refName(refName), m_circuit(circuit), m_level(level), m_name(name),
m_field(field), m_hasValues(hasValues), m_message(NULL) { } m_dstAddress(dstAddress), m_field(field), m_hasValues(hasValues), m_message(NULL) { }
/** /**
* Destructor. * Destructor.
@@ -891,6 +928,9 @@ class SimpleCondition : public Condition {
/** the circuit name. */ /** the circuit name. */
const string m_circuit; const string m_circuit;
/** the access level. */
const string m_level;
/** the message name, or empty for scan message. */ /** the message name, or empty for scan message. */
const string m_name; const string m_name;
@@ -919,14 +959,15 @@ class SimpleNumericCondition : public SimpleCondition {
* @param condName the name of the condition. * @param condName the name of the condition.
* @param refName the reference name for dumping. * @param refName the reference name for dumping.
* @param circuit the circuit name. * @param circuit the circuit name.
* @param level the access level.
* @param name the message name, or empty for scan message. * @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 as well as scan message). * @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.
*/ */
SimpleNumericCondition(const string condName, const string refName, const string circuit, const string name, SimpleNumericCondition(const string condName, const string refName, const string circuit, const string level,
const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges) const string name, const unsigned char dstAddress, const string field, const vector<unsigned int> valueRanges)
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true), : SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
m_valueRanges(valueRanges) { } m_valueRanges(valueRanges) { }
/** /**
@@ -956,14 +997,15 @@ class SimpleStringCondition : public SimpleCondition {
* @param condName the name of the condition. * @param condName the name of the condition.
* @param refName the reference name for dumping. * @param refName the reference name for dumping.
* @param circuit the circuit name. * @param circuit the circuit name.
* @param level the access level.
* @param name the message name, or empty for scan message. * @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 as well as scan message). * @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 values the valid values. * @param values the valid values.
*/ */
SimpleStringCondition(const string condName, const string refName, const string circuit, const string name, SimpleStringCondition(const string condName, const string refName, const string circuit, const string level,
const unsigned char dstAddress, const string field, const vector<string> values) const string name, const unsigned char dstAddress, const string field, const vector<string> values)
: SimpleCondition(condName, refName, circuit, name, dstAddress, field, true), : SimpleCondition(condName, refName, circuit, level, name, dstAddress, field, true),
m_values(values) { } m_values(values) { }
/** /**
@@ -1258,17 +1300,20 @@ class MessageMap : public FileReader {
* Find the @a Message instance for the specified circuit and name. * Find the @a Message instance for the specified circuit and name.
* @param circuit the optional circuit name. * @param circuit the optional circuit name.
* @param name the message name. * @param name the message name.
* @param levels the access levels to match.
* @param isWrite whether this is a write message. * @param isWrite whether this is a write message.
* @param isPassive whether this is a passive message. * @param isPassive whether this is a passive message.
* @return the @a Message instance, or NULL. * @return the @a Message instance, or NULL.
* Note: the caller may not free the returned instance. * Note: the caller may not free the returned instance.
*/ */
Message* find(const string& circuit, const string& name, const bool isWrite, const bool isPassive = false); Message* find(const string& circuit, const string& name, const string& levels, const bool isWrite,
const bool isPassive = false);
/** /**
* Find all active get @a Message instances for the specified circuit and name. * Find all active get @a Message instances for the specified circuit and name.
* @param circuit the circuit name, or empty for any. * @param circuit the circuit name, or empty for any.
* @param name the message name, or empty for any. * @param name the message name, or empty for any.
* @param levels the access levels to match.
* @param completeMatch false to also include messages where the circuit and name matches only a part of the given * @param completeMatch false to also include messages where the circuit and name matches only a part of the given
* circuit and name (default true). * circuit and name (default true).
* @param withRead true to include read messages (default true). * @param withRead true to include read messages (default true).
@@ -1284,9 +1329,9 @@ class MessageMap : public FileReader {
* address), or 0 to ignore. * address), or 0 to ignore.
* Note: the caller may not free the returned instances. * Note: the caller may not free the returned instances.
*/ */
deque<Message*> findAll(const string& circuit, const string& name, const bool completeMatch = true, deque<Message*> findAll(const string& circuit, const string& name, const string& levels,
const bool withRead = true, const bool withWrite = false, const bool withPassive = false, const bool completeMatch = true, const bool withRead = true, const bool withWrite = false,
const bool completeMatchIgnoreCircuitSuffix = false, const bool onlyAvailable = true, const bool withPassive = false, const bool onlyAvailable = true,
const time_t since = 0, const time_t until = 0); const time_t since = 0, const time_t until = 0);
/** /**
+1 -1
View File
@@ -161,7 +161,7 @@ int main() {
"ff08b509030d6900", "02133f", "md" }, "ff08b509030d6900", "02133f", "md" },
{"r,cir*cuit#level,na*me,com*ment,ff,75,b509,0d", "", "", "", "defaults" }, {"r,cir*cuit#level,na*me,com*ment,ff,75,b509,0d", "", "", "", "defaults" },
{"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH", {"r,CIRCUIT,NAME,COMMENT,,,,0100,field,,UCH",
"r,cirCIRCUITcuit#level,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42", "r,cirCIRCUITcuit,naNAMEme,comCOMMENTment,ff,75,b509,0d0100,field,s,UCH,,,: field=42",
"ff08b509030d0100", "012a", "mDN"}, "ff08b509030d0100", "012a", "mDN"},
}; };
templates = new DataFieldTemplates(); templates = new DataFieldTemplates();