removed fieldIds again in favor of strings (to support custom attributes), corrected JSON format, require circuit in message definition, support custom message attributes in find command

This commit is contained in:
john30
2017-04-16 16:53:39 +02:00
parent 6c9230322a
commit f5c5e34d90
6 changed files with 184 additions and 337 deletions
+4 -4
View File
@@ -1087,7 +1087,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
bool configFormat = false, exact = false, withRead = true, withWrite = false, withPassive = true, first = true,
onlyWithData = false, hexFormat = false, userLevel = true;
OutputFormat verbosity = 0;
vector<size_t> fieldIds;
vector<string> fieldNames;
string circuit;
vector<symbol_t> id;
while (args.size() > argPos && args[argPos][0] == '-') {
@@ -1121,7 +1121,7 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
argPos = 0; // print usage
break;
}
if (!Message::extractFieldIds(args[argPos], fieldIds)) {
if (!Message::extractFieldNames(args[argPos], fieldNames)) {
argPos = 0; // print usage
break;
}
@@ -1231,11 +1231,11 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
result << endl;
}
message->dump(result);
} else if (!fieldIds.empty()) {
} else if (!fieldNames.empty()) {
if (found) {
result << endl;
}
message->dump(result, &fieldIds);
message->dump(result, &fieldNames);
} else {
if (found) {
result << endl;
+15 -25
View File
@@ -176,13 +176,6 @@ static const char* knownFieldNames[] = {
"field",
};
/** the known topic field IDs. */
static const size_t knownFieldIds[] = {
MESSAGEFIELD_CIRCUIT,
MESSAGEFIELD_NAME,
MESSAGEFIELD_DATAFIELDS,
};
/** the number of known field names. */
static const size_t knownFieldCount = sizeof(knownFieldNames) / sizeof(char*);
@@ -194,7 +187,7 @@ static const size_t knownFieldCount = sizeof(knownFieldNames) / sizeof(char*);
* @param fields the @a vector to which the field parts shall be added.
* @return true on success, false on malformed topic template.
*/
bool parseTopic(const string topic, vector<string> &strs, vector<size_t> &fields) {
bool parseTopic(const string topic, vector<string> &strs, vector<string> &fields) {
size_t lastpos = 0;
size_t end = topic.length();
vector<string> columns;
@@ -208,17 +201,17 @@ bool parseTopic(const string topic, vector<string> &strs, vector<size_t> &fields
break;
}
}
if (idx== knownFieldCount) {
if (idx == knownFieldCount) { // TODO could allow custom attributes here
return false;
}
size_t fieldId = knownFieldIds[idx];
for (vector<size_t>::iterator it=fields.begin(); it != fields.end(); it++) {
if (*it == fieldId) {
string fieldName = knownFieldNames[idx];
for (auto& it : fields) {
if (it == fieldName) {
return false; // duplicate column
}
}
strs.push_back(topic.substr(lastpos, pos-lastpos));
fields.push_back(fieldId);
fields.push_back(fieldName);
lastpos = pos+1+len;
pos = topic.find('%', lastpos);
}
@@ -288,12 +281,12 @@ MqttHandler::MqttHandler(UserInfo* userInfo, BusHandler* busHandler, MessageMap*
m_topicStrs[0] = str+"/";
}
}
m_topicFields.push_back(MESSAGEFIELD_CIRCUIT); // circuit
m_topicFields.push_back("circuit");
m_topicStrs.push_back("/");
m_topicFields.push_back(MESSAGEFIELD_NAME); // name
m_topicFields.push_back("name");
} else {
for (size_t i = 0; i < m_topicFields.size(); i++) {
if (m_topicFields[i] == MESSAGEFIELD_DATAFIELDS) { // fields
if (m_topicFields[i] == "fields") {
m_publishByField = true;
break;
}
@@ -439,17 +432,14 @@ void MqttHandler::notifyTopic(string topic, string data) {
if (field.empty()) {
return;
}
switch (m_topicFields[idx-1]) {
case MESSAGEFIELD_CIRCUIT:
string fieldName = m_topicFields[idx-1];
if (fieldName == "circuit") {
circuit = field;
break;
case MESSAGEFIELD_NAME:
} else if (fieldName == "name") {
name = field;
break;
case MESSAGEFIELD_DATAFIELDS:
} else if (fieldName == "fields") {
// field = field; // TODO add support for writing a single field
break;
default:
} else {
return;
}
}
@@ -576,7 +566,7 @@ string MqttHandler::getTopic(Message* message, ssize_t fieldIndex) {
break;
}
if (i < m_topicFields.size()) {
if (m_topicFields[i] == MESSAGEFIELD_DATAFIELDS && fieldIndex >= 0) {
if (m_topicFields[i] == "fields" && fieldIndex >= 0) {
ret << message->getFieldName(fieldIndex); // TODO skip ignored fields
} else {
message->dumpField(ret, m_topicFields[i]);
+1 -1
View File
@@ -124,7 +124,7 @@ class MqttHandler : public DataSink, public DataSource, public Thread {
vector<string> m_topicStrs;
/** the MQTT topic field parts. */
vector<size_t> m_topicFields;
vector<string> m_topicFields;
/** the global topic prefix. */
string m_globalTopic;
+34 -58
View File
@@ -38,45 +38,37 @@ using std::setw;
/** the week day names. */
static const char* dayNames[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
size_t getDataFieldId(const string name) {
if (name == "name" || name.find("field") != string::npos) {
return DATAFIELD_NAME;
/** the default field map for field templates. */
static const char* defaultTemplateFieldMap[] = {
"name", "*type", "divisor/values", "unit", "comment",
"*name", "type", "divisor/values", "unit", "comment",
};
string getDataFieldName(const string name) {
if (name.find("name") != string::npos || name.find("field") != string::npos) {
return "name";
}
if (name.find("part") != string::npos) {
return DATAFIELD_PART;
return "part";
}
if (name.find("type") != string::npos) {
return DATAFIELD_TYPE;
}
if (name.find("divisor") != string::npos || name.find("values") != string::npos) {
return DATAFIELD_DIVISORVALUES;
}
if (name == "unit") {
return DATAFIELD_UNIT;
}
if (name == "comment") {
return DATAFIELD_COMMENT;
}
return UINT_MAX;
}
string getDataFieldName(const size_t fieldId) {
switch (fieldId) {
case DATAFIELD_NAME:
return "name";
case DATAFIELD_PART:
return "part";
case DATAFIELD_TYPE:
return "type";
case DATAFIELD_DIVISORVALUES:
return "divisor/values";
case DATAFIELD_UNIT:
return "unit";
case DATAFIELD_COMMENT:
return "comment";
default:
return "";
}
if (name.find("divisor") != string::npos) {
if (name.find("values") != string::npos) {
return "divisor/values";
}
return "divisor";
}
if (name == "values" || name == "unit") {
return name;
}
if (name.find("comment") != string::npos) {
return "comment";
}
return "";
}
@@ -117,7 +109,7 @@ void AttributedItem::appendJson(ostream& output, const string name, const string
if (prependFieldSeparator) {
output << FIELD_SEPARATOR;
}
output << "\"" << name << "\": ";
output << " \"" << name << "\": ";
if (plain) {
output << value;
} else {
@@ -1132,24 +1124,8 @@ result_t DataFieldTemplates::getFieldMap(vector<string>& row, string& errorDescr
// name[:usename],basetype[:len]|template[:usename][,[divisor|values][,[unit][,[comment]]]]
if (row.empty()) {
// default map does not include separate field name
row.push_back("name");
for (size_t cnt = 0; cnt < 2; cnt++) {
bool first = true;
for (size_t fieldId = DATAFIELD_RANGE_MIN; fieldId <= DATAFIELD_RANGE_MAX; fieldId++) {
if (cnt == 0 && fieldId == DATAFIELD_NAME) {
continue;
}
if (fieldId == DATAFIELD_PART) { // not included in default map
continue;
}
// subsequent fields start with field name
if (first) {
first = false;
row.push_back("*"+getDataFieldName(fieldId));
} else {
row.push_back(getDataFieldName(fieldId));
}
}
for (auto col : defaultTemplateFieldMap) {
row.push_back(col);
}
return RESULT_OK;
}
@@ -1159,9 +1135,9 @@ result_t DataFieldTemplates::getFieldMap(vector<string>& row, string& errorDescr
string useName = name;
tolower(useName);
if (inDataFields) {
size_t fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
useName = getDataFieldName(fieldId);
string chkName = getDataFieldName(useName);
if (!chkName.empty()) {
useName = chkName;
if (seen.find(useName) != seen.end()) {
if (seen.find("type") == seen.end()) {
errorDescription = "missing type";
@@ -1174,9 +1150,9 @@ result_t DataFieldTemplates::getFieldMap(vector<string>& row, string& errorDescr
if (useName == "name" && seen.find("name") == seen.end()) {
// keep first name for template
} else {
size_t fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
useName = getDataFieldName(fieldId);
string chkName = getDataFieldName(useName);
if (!chkName.empty()) {
useName = chkName;
if (seen.find("name") == seen.end()) {
errorDescription = "missing name";
return RESULT_ERR_EOF; // require at least name
+120 -203
View File
@@ -57,109 +57,52 @@ using std::endl;
/** the maximum poll priority for a @a Message referred to by a @a Condition. */
#define POLL_PRIORITY_CONDITION 5
/** the known field names (pairs of full length name and short length name). */
static const char* knownFieldNames[] = {
"type", "t",
"circuit", "c",
"level", "l",
"name", "n",
"comment", "co",
"qq", "q",
"zz", "z",
"pbsb", "p",
"id", "i",
"fields", "f",
/** the known full length field names. */
static const char* knownFieldNamesFull[] = {
"type", "circuit", "level", "name", "comment", "qq", "zz", "pbsb", "id", "fields",
};
/** the known field IDs according to @a knownFieldNames. */
static const size_t knownFieldIds[] = {
MESSAGEFIELD_TYPE, MESSAGEFIELD_TYPE,
MESSAGEFIELD_CIRCUIT, MESSAGEFIELD_CIRCUIT,
MESSAGEFIELD_LEVEL, MESSAGEFIELD_LEVEL,
MESSAGEFIELD_NAME, MESSAGEFIELD_NAME,
MESSAGEFIELD_COMMENT, MESSAGEFIELD_COMMENT,
MESSAGEFIELD_QQ, MESSAGEFIELD_QQ,
MESSAGEFIELD_ZZ, MESSAGEFIELD_ZZ,
MESSAGEFIELD_PBSB, MESSAGEFIELD_PBSB,
MESSAGEFIELD_ID, MESSAGEFIELD_ID,
MESSAGEFIELD_DATAFIELDS, MESSAGEFIELD_DATAFIELDS,
/** the known full length field names. */
static const char* knownFieldNamesShort[] = {
"t", "c", "l", "n", "co", "q", "z", "p", "i", "f",
};
/** the number of known field names. */
static const size_t knownFieldCount = sizeof(knownFieldNames) / sizeof(char*);
static const size_t knownFieldCount = sizeof(knownFieldNamesFull) / sizeof(char*);
/** the default field map for messages. */
static const char* defaultMessageFieldMap[] = { // access level not included in default map
"type", "circuit", "name", "comment", "qq", "zz", "pbsb", "id",
"*name", "part", "type", "divisor/values", "unit", "comment",
};
extern DataFieldTemplates* getTemplates(const string filename);
/**
* Get the message field ID for the given field name.
* @param name the field name.
* @return the field ID, or @a UINT_MAX if not found.
* Get the normalized message field name for the given name.
* @param name the input field name.
* @return the normalized message field name, or empty if unknown.
*/
size_t getMessageFieldId(const string name) {
string getMessageFieldName(const string name) {
if (name.find("type") != string::npos) {
return MESSAGEFIELD_TYPE;
}
if (name == "circuit") {
return MESSAGEFIELD_CIRCUIT;
}
if (name == "level") {
return MESSAGEFIELD_LEVEL;
}
if (name == "name") {
return MESSAGEFIELD_NAME;
}
if (name == "comment") {
return MESSAGEFIELD_COMMENT;
}
if (name == "qq") {
return MESSAGEFIELD_QQ;
}
if (name == "zz") {
return MESSAGEFIELD_ZZ;
}
if (name == "pbsb") {
return MESSAGEFIELD_PBSB;
}
if (name == "id") {
return MESSAGEFIELD_ID;
}
return UINT_MAX;
}
/**
* Get the message field name for the given field ID.
* @param fieldId the field ID.
* @param withDataFields whether to include the data fields ID or not.
* @return the field name, or empty if not found.
*/
string getMessageFieldName(size_t fieldId, bool withDataFields = true) {
switch (fieldId) {
case MESSAGEFIELD_TYPE:
return "type";
case MESSAGEFIELD_CIRCUIT:
return "circuit";
case MESSAGEFIELD_LEVEL:
return "level";
case MESSAGEFIELD_NAME:
return "name";
case MESSAGEFIELD_COMMENT:
return "comment";
case MESSAGEFIELD_QQ:
return "qq";
case MESSAGEFIELD_ZZ:
return "zz";
case MESSAGEFIELD_PBSB:
return "pbsb";
case MESSAGEFIELD_ID:
return "id";
case MESSAGEFIELD_DATAFIELDS:
return withDataFields ? "fields" : "";
default:
return "";
}
if (name == "circuit" || name == "level" || name == "qq" || name == "zz" || name == "pbsb" || name == "id") {
return name;
}
if (name.find("name") != string::npos) {
return "name";
}
if (name.find("comment") == 0) {
return "comment";
}
return "";
}
/* case MESSAGEFIELD_DATAFIELDS:
return withDataFields ? "fields" : "";
*/
Message::Message(const string circuit, const string level, const string name,
const bool isWrite, const bool isPassive, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress,
@@ -187,11 +130,11 @@ Message::Message(const string circuit, const string level, const string name,
: AttributedItem(name), m_circuit(circuit), m_level(level), m_isWrite(broadcast),
m_isPassive(false),
m_srcAddress(SYN), m_dstAddress(broadcast ? BROADCAST : SYN),
m_id({pb, sb}), m_data(data), m_deleteData(deleteData),
m_id({pb, sb}), m_key(createKey(pb, sb, broadcast)),
m_data(data), m_deleteData(deleteData),
m_pollPriority(0),
m_usedByCondition(false), m_isScanMessage(true), m_condition(NULL),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0),
m_key(createKey(pb, sb, broadcast)) {
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
}
@@ -352,6 +295,10 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
level = circuit.substr(pos+1);
circuit.resize(pos);
}
if (circuit.empty()) {
errorDescription = "circuit";
return RESULT_ERR_MISSING_ARG; // empty circuit
}
string name = getDefault(pluck(row, "name"), defaults, "name", true, true); // name
if (name.empty()) {
errorDescription = "name";
@@ -545,25 +492,26 @@ Message* Message::createScanMessage(bool broadcast) {
return new Message("scan", "", "", 0x07, 0x04, broadcast, DataFieldSet::getIdentFields(), !broadcast);
}
bool Message::extractFieldIds(string str, vector<size_t>& fields, bool checkAbbreviated) {
bool Message::extractFieldNames(string str, vector<string>& fields, bool checkAbbreviated) {
istringstream input(str);
vector<string> row;
string column;
while (getline(input, column, FIELD_SEPARATOR)) {
size_t idx = knownFieldCount;
for (size_t i = 0; i < knownFieldCount; i++) {
if (column == knownFieldNames[i]) {
if (column == knownFieldNamesFull[i]) {
idx = i;
break;
}
if (!checkAbbreviated) {
i++;
if (checkAbbreviated && column == knownFieldNamesShort[i]) {
idx = i;
break;
}
}
if (idx == knownFieldCount) {
return false;
}
fields.push_back(knownFieldIds[idx]);
if (idx != knownFieldCount) {
column = knownFieldNamesFull[idx];
} // else: custom attribute
fields.push_back(column);
}
return !fields.empty();
}
@@ -874,11 +822,34 @@ bool Message::isLessPollWeight(const Message* other) const {
return false;
}
void Message::dumpHeader(ostream& output, vector<size_t>* fieldIds) {
void Message::dumpHeader(ostream& output, vector<string>* fieldNames) {
bool first = true;
if (fieldIds == NULL) {
for (size_t fieldId = MESSAGEFIELD_RANGE_MIN; fieldId <= MESSAGEFIELD_RANGE_MAX; fieldId++) {
if (fieldId == MESSAGEFIELD_LEVEL) {
if (fieldNames == NULL) {
for (auto fieldName : defaultMessageFieldMap) {
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
output << fieldName;
}
return;
}
for (auto fieldName : *fieldNames) {
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
output << fieldName;
}
}
void Message::dump(ostream& output, vector<string>* fieldNames, bool withConditions) const {
bool first = true;
if (fieldNames == NULL) {
for (auto fieldName : knownFieldNamesFull) {
if (fieldName == "level") {
continue; // access level not included in default dump format
}
if (first) {
@@ -886,67 +857,22 @@ void Message::dumpHeader(ostream& output, vector<size_t>* fieldIds) {
} else {
output << FIELD_SEPARATOR;
}
if (fieldId == MESSAGEFIELD_DATAFIELDS) {
bool dataFirst = true;
for (size_t dataFieldId = DATAFIELD_RANGE_MIN; dataFieldId <= DATAFIELD_RANGE_MAX; dataFieldId++) {
// subsequent fields start with field name
if (dataFirst) {
dataFirst = false;
output << "*";
} else {
output << FIELD_SEPARATOR;
}
output << getDataFieldName(dataFieldId);
}
} else {
output << getMessageFieldName(fieldId, false);
}
dumpField(output, fieldName, withConditions);
}
return;
}
for (auto fieldId : *fieldIds) {
for (auto fieldName : *fieldNames) {
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
string name = getMessageFieldName(fieldId, false);
if (name.empty()) {
name = getDataFieldName(fieldId);
}
output << name;
dumpField(output, fieldName, withConditions);
}
}
void Message::dump(ostream& output, vector<size_t>* fieldIds, bool withConditions) const {
bool first = true;
if (fieldIds == NULL) {
for (size_t fieldId = MESSAGEFIELD_RANGE_MIN; fieldId <= MESSAGEFIELD_RANGE_MAX; fieldId++) {
if (fieldId == MESSAGEFIELD_LEVEL) {
continue; // access level not included in default dump format
}
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
dumpField(output, fieldId, withConditions);
}
return;
}
for (auto fieldId : *fieldIds) {
if (first) {
first = false;
} else {
output << FIELD_SEPARATOR;
}
dumpField(output, fieldId, withConditions);
}
}
void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) const {
switch (fieldId) {
case MESSAGEFIELD_TYPE:
void Message::dumpField(ostream& output, string fieldName, bool withConditions) const {
if (fieldName == "type") {
if (withConditions && m_condition != NULL) {
m_condition->dump(output);
}
@@ -963,45 +889,49 @@ void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) co
output << static_cast<unsigned>(m_pollPriority);
}
}
break;
case MESSAGEFIELD_CIRCUIT:
return;
}
if (fieldName == "circuit") {
dumpString(output, m_circuit, false);
break;
case MESSAGEFIELD_LEVEL:
return;
}
if (fieldName == "level") {
dumpString(output, m_level, false);
break;
case MESSAGEFIELD_NAME:
return;
}
if (fieldName == "name") {
dumpString(output, m_name, false);
break;
case MESSAGEFIELD_COMMENT:
dumpAttribute(output, "comment", false);
break;
case MESSAGEFIELD_QQ:
return;
}
if (fieldName == "qq") {
if (m_srcAddress != SYN) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_srcAddress);
}
break;
case MESSAGEFIELD_ZZ:
return;
}
if (fieldName == "zz") {
if (m_dstAddress != SYN) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(m_dstAddress);
}
break;
case MESSAGEFIELD_PBSB:
return;
}
if (fieldName == "pbsb") {
for (vector<symbol_t>::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);
}
break;
case MESSAGEFIELD_ID:
return;
}
if (fieldName == "id") {
for (vector<symbol_t>::const_iterator it = m_id.begin()+2; it < m_id.end(); it++) {
output << hex << setw(2) << setfill('0') << static_cast<unsigned>(*it);
}
break;
case MESSAGEFIELD_DATAFIELDS:
m_data->dump(output);
break;
default:
break;
return;
}
if (fieldName == "fields") {
m_data->dump(output);
return;
}
dumpAttribute(output, fieldName, false);
}
void Message::decode(ostringstream& output, OutputFormat outputFormat, bool leadingSeparator,
@@ -1278,9 +1208,9 @@ result_t ChainedMessage::combineLastParts() {
return result;
}
void ChainedMessage::dumpField(ostream& output, size_t fieldId, bool withConditions) const {
if (fieldId != MESSAGEFIELD_ID) {
Message::dumpField(output, fieldId, withConditions);
void ChainedMessage::dumpField(ostream& output, string fieldName, bool withConditions) const {
if (fieldName != "id") {
Message::dumpField(output, fieldName, withConditions);
return;
}
bool first = true;
@@ -1847,21 +1777,8 @@ result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription)
// unit,comment
// minimum: type,name,PBSB,field,datatype
if (row.empty()) {
for (size_t fieldId = MESSAGEFIELD_RANGE_MIN; fieldId <= MESSAGEFIELD_RANGE_MAX; fieldId++) {
if (fieldId == MESSAGEFIELD_LEVEL) {
continue; // level not part of default field list
}
if (fieldId == MESSAGEFIELD_DATAFIELDS) {
continue; // data fields are handled below
}
row.push_back(getMessageFieldName(fieldId));
}
for (size_t fieldId = DATAFIELD_RANGE_MIN; fieldId <= DATAFIELD_RANGE_MAX; fieldId++) {
if (fieldId == DATAFIELD_RANGE_MIN) {
row.push_back("*" + getDataFieldName(fieldId)); // field repetition
} else {
row.push_back(getDataFieldName(fieldId));
}
for (auto col : defaultMessageFieldMap) {
row.push_back(col);
}
return RESULT_OK;
}
@@ -1871,9 +1788,9 @@ result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription)
string useName = name;
tolower(useName);
if (inDataFields) {
size_t fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
useName = getDataFieldName(fieldId);
string chkName = getDataFieldName(useName);
if (!chkName.empty()) {
useName = chkName;
if (seen.find(useName) != seen.end()) {
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
errorDescription = "missing field name/type as of already seen "+useName;
@@ -1883,13 +1800,13 @@ result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription)
}
}
} else {
size_t fieldId = getMessageFieldId(useName);
if (fieldId != UINT_MAX && (fieldId != MESSAGEFIELD_NAME || seen.find("name") == seen.end())) {
useName = getMessageFieldName(fieldId);
string chkName = getMessageFieldName(useName);
if (!chkName.empty() && (chkName != "name" || seen.find("name") == seen.end())) {
useName = chkName;
} else {
fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
useName = getDataFieldName(fieldId);
chkName = getDataFieldName(useName);
if (!chkName.empty()) {
useName = chkName;
if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
errorDescription = "missing message name/type/pbsb";
return RESULT_ERR_EOF; // require at least type, name, and pbsb
+10 -46
View File
@@ -68,42 +68,6 @@ class SimpleCondition;
class CombinedCondition;
class MessageMap;
/** the field ID in @a Message::dump() for the message type. */
#define MESSAGEFIELD_TYPE (DATAFIELD_RANGE_MAX+1)
/** the field ID in @a Message::dump() for the circuit name. */
#define MESSAGEFIELD_CIRCUIT (MESSAGEFIELD_TYPE+1)
/** the field ID in @a Message::dump() for the access level. */
#define MESSAGEFIELD_LEVEL (MESSAGEFIELD_CIRCUIT+1)
/** the field ID in @a Message::dump() for the message name. */
#define MESSAGEFIELD_NAME (MESSAGEFIELD_LEVEL+1)
/** the field ID in @a Message::dump() for the message comment. */
#define MESSAGEFIELD_COMMENT (MESSAGEFIELD_NAME+1)
/** the field ID in @a Message::dump() for the source address QQ. */
#define MESSAGEFIELD_QQ (MESSAGEFIELD_COMMENT+1)
/** the field ID in @a Message::dump() for the destination address QQ. */
#define MESSAGEFIELD_ZZ (MESSAGEFIELD_QQ+1)
/** the field ID in @a Message::dump() for the PBSB bytes. */
#define MESSAGEFIELD_PBSB (MESSAGEFIELD_ZZ+1)
/** the field ID in @a Message::dump() for the ID field (after the PBSB bytes). */
#define MESSAGEFIELD_ID (MESSAGEFIELD_PBSB+1)
/** the field ID in @a Message::dump() for the data field(s). */
#define MESSAGEFIELD_DATAFIELDS (MESSAGEFIELD_ID+1)
/** the marker field ID for the minimum field ID. */
#define MESSAGEFIELD_RANGE_MIN MESSAGEFIELD_TYPE
/** the marker field ID for the maximum field ID. */
#define MESSAGEFIELD_RANGE_MAX MESSAGEFIELD_DATAFIELDS
/**
* Defines parameters of a message sent or received on the bus.
@@ -235,13 +199,13 @@ class Message : public AttributedItem {
static Message* createScanMessage(bool broadcast = false);
/**
* Extract the known field IDs from the input string.
* Extract the known field names from the input string.
* @param str the input string with the field names separated by @a FIELD_SEPARATOR.
* @param fields the vector to update with the extracted field IDs with.
* @param fields the vector to update with the extracted normalized field names with.
* @param checkAbbreviated true to also check for abbreviated field names.
* @return true when all fields are valid.
*/
static bool extractFieldIds(string str, vector<size_t>& fields, bool checkAbbreviated = true);
static bool extractFieldNames(string str, vector<string>& fields, bool checkAbbreviated = true);
/**
* Set that this is a special scanning @a Message instance.
@@ -577,25 +541,25 @@ class Message : public AttributedItem {
/**
* Write the message definition header or parts of it to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldIds the list of field IDs to write, or NULL for all (see @p MESSAGEFIELD_TYPE constants).
* @param fieldNames the list of field names to write, or NULL for all.
*/
static void dumpHeader(ostream& output, vector<size_t>* fieldIds = NULL);
static void dumpHeader(ostream& output, vector<string>* fieldNames = NULL);
/**
* Write the message definition or parts of it to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldIds the list of field IDs to write, or NULL for all (see @p MESSAGEFIELD_TYPE constants).
* @param fieldNames the list of field names to write, or NULL for all.
* @param withConditions whether to include the optional conditions prefix.
*/
void dump(ostream& output, vector<size_t>* fieldIds = NULL, bool withConditions = false) const;
void dump(ostream& output, vector<string>* fieldNames = NULL, bool withConditions = false) const;
/**
* Write the specified field to the @a ostream.
* @param output the @a ostream to append the formatted value to.
* @param fieldId the field ID to write (see @p MESSAGEFIELD_TYPE constants).
* @param fieldName the field name to write.
* @param withConditions whether to include the optional conditions prefix.
*/
virtual void dumpField(ostream& output, size_t fieldId, bool withConditions = false) const;
virtual void dumpField(ostream& output, string fieldName, bool withConditions = false) const;
/**
* Decode the message from the last stored data.
@@ -765,7 +729,7 @@ class ChainedMessage : public Message {
protected:
// @copydoc
void dumpField(ostream& output, size_t fieldId, bool withConditions = false) const override;
void dumpField(ostream& output, string fieldName, bool withConditions = false) const override;
private: