diff --git a/src/lib/ebus/filereader.h b/src/lib/ebus/filereader.h index 6d968663..a5707320 100644 --- a/src/lib/ebus/filereader.h +++ b/src/lib/ebus/filereader.h @@ -41,6 +41,7 @@ using namespace std; extern void printErrorPos(ostream& out, vector::iterator begin, const vector::iterator end, vector::iterator pos, string filename, size_t lineNo, result_t result); +extern unsigned int parseInt(const char* str, int base, const unsigned int minValue, const unsigned int maxValue, result_t& result, unsigned int* length); /** * An abstract class that support reading definitions from a file. @@ -76,9 +77,26 @@ public: return RESULT_ERR_NOTFOUND; string line; + size_t firstDot = filename.find_first_of('.'); + string defaultDest = ""; + string defaultCircuit = ""; + if (firstDot==2) { // potential destination address, matches "^ZZ." + result_t result; + defaultDest = filename.substr(0, 2); + int zz = parseInt(defaultDest.c_str(), 16, 0, 0xff, result, NULL); + if (result!=RESULT_OK || !isValidAddress(zz)) + defaultDest = ""; // invalid: not in hex or no master/slave/broadcast address + else { + size_t lastDot = filename.find_last_of('.'); + if (lastDot>firstDot && lastDot-firstDot<=5) { // potential ident, matches "^ZZ.IDENT." + defaultCircuit = filename.substr(firstDot+1, lastDot-firstDot); + if (defaultCircuit.find_first_of(' ')!=string::npos) + defaultCircuit = ""; // invalid: contains spaces + } + } + } unsigned int lineNo = 0; vector row; - string token; vector< vector > defaults; while (getline(ifs, line) != 0) { lineNo++; @@ -138,7 +156,7 @@ public: if (m_supportsDefaults) { if (line[0] == '*') { row[0] = row[0].substr(1); - result = addDefaultFromFile(defaults, row, it, filename, lineNo); + result = addDefaultFromFile(defaults, row, it, defaultDest, defaultCircuit, filename, lineNo); if (result == RESULT_OK) continue; } else @@ -175,11 +193,19 @@ public: * @param defaults the list to add the default row to. * @param row the default row (initial star char removed). * @param begin an iterator to the first column of the default row to read (for error reporting). + * @param defaultDest the valid destination address extracted from the file name (from ZZ part), or empty. + * @param defaultCircuit the valid circuit name extracted from the file name (from IDENT part), or empty. * @param filename the name of the file being read. * @param lineNo the current line number in the file being read. * @return @a RESULT_OK on success, or an error code. */ - virtual result_t addDefaultFromFile(vector< vector >& defaults, vector& row, vector::iterator& begin, const string& filename, unsigned int lineNo) { + virtual result_t addDefaultFromFile(vector< vector >& defaults, vector& row, + vector::iterator& begin, string defaultDest, string defaultCircuit, + const string& filename, unsigned int lineNo) { + if (row.size()>1 && defaultCircuit.length()>0 && row[1].length()==0) + row[1] = defaultCircuit; + if (row.size()>5 && defaultDest.length()>0 && row[5].length()==0) + row[5] = defaultDest; defaults.push_back(row); begin = row.end(); return RESULT_OK; @@ -195,7 +221,9 @@ public: * @param lineNo the current line number in the file being read. * @return @a RESULT_OK on success, or an error code. */ - virtual result_t addFromFile(vector::iterator& begin, const vector::iterator end, T arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) = 0; + virtual result_t addFromFile(vector::iterator& begin, const vector::iterator end, + T arg, vector< vector >* defaults, + const string& filename, unsigned int lineNo) = 0; /** * Left and right trim the string. diff --git a/src/lib/ebus/message.cpp b/src/lib/ebus/message.cpp index ff33cfda..789adf27 100644 --- a/src/lib/ebus/message.cpp +++ b/src/lib/ebus/message.cpp @@ -98,7 +98,7 @@ string getDefault(const string value, vector* defaults, size_t pos) } result_t Message::create(vector::iterator& it, const vector::iterator end, - vector< vector >* defaultsRows, map* conditions, const string& filename, + vector< vector >* defaultsRows, Condition* condition, const string& filename, DataFieldTemplates* templates, vector& messages) { // [type],[circuit],name,[comment],[QQ[;QQ]*],[ZZ],[PBSB],[ID],fields... @@ -111,21 +111,6 @@ result_t Message::create(vector::iterator& it, const vector::ite return RESULT_ERR_EOF; string typeStr = *it++; - Condition* condition = NULL; - if (conditions && typeStr.length()>0 && typeStr[0]=='[') { - // condition - size_t pos = typeStr.find(']'); - if (pos!=string::npos) { - string type = typeStr.substr(1, pos-1); - string key = filename+":"+type; - map::iterator it = conditions->find(key); - if (it==conditions->end()) - return RESULT_ERR_NOTFOUND; - condition = it->second; - typeStr = typeStr.substr(pos+1); - } - } - const char* str = typeStr.c_str(); // [type] if (it == end) return RESULT_ERR_EOF; @@ -755,8 +740,10 @@ result_t MessageMap::add(Message* message) bool conditional = message->isConditional(); map >::iterator keyIt = m_messagesByKey.find(key); if (keyIt != m_messagesByKey.end()) { + if (!conditional) + return RESULT_ERR_DUPLICATE; // duplicate key vector* messages = &keyIt->second; - if (!messages->front()->isConditional() || !conditional) + if (!messages->front()->isConditional()) return RESULT_ERR_DUPLICATE; // duplicate key } bool isPassive = message->isPassive(); @@ -798,7 +785,9 @@ result_t MessageMap::add(Message* message) return RESULT_OK; } -result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vector& row, vector::iterator& begin, const string& filename, unsigned int lineNo) +result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vector& row, + vector::iterator& begin, string defaultDest, string defaultCircuit, + const string& filename, unsigned int lineNo) { // convert conditions in defaults string type = row[0]; @@ -811,6 +800,8 @@ result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vect if (it != m_conditions.end()) return RESULT_ERR_DUPLICATE_NAME; + if (row.size()>1 && defaultCircuit.length()>0 && row[1].length()==0) + row[1] = defaultCircuit; Condition* condition = NULL; result_t result = Condition::create(++begin, row.end(), condition); if (result!=RESULT_OK) { @@ -824,13 +815,28 @@ result_t MessageMap::addDefaultFromFile(vector< vector >& defaults, vect m_conditions[key] = condition; return RESULT_OK; } - return FileReader::addDefaultFromFile(defaults, row, begin, filename, lineNo); + return FileReader::addDefaultFromFile(defaults, row, begin, defaultDest, defaultCircuit, filename, lineNo); } -result_t MessageMap::addFromFile(vector::iterator& begin, const vector::iterator end, DataFieldTemplates* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo) +result_t MessageMap::addFromFile(vector::iterator& begin, const vector::iterator end, + DataFieldTemplates* arg, vector< vector >* defaults, + const string& filename, unsigned int lineNo) { vector::iterator restart = begin; + Condition* condition = NULL; string types = *restart; + if (types.length()>0 && types[0]=='[') { + // condition + size_t pos = types.find(']'); + if (pos!=string::npos) { + string key = filename+":"+types.substr(1, pos-1); + map::iterator it = m_conditions.find(key); // TODO add support for global conditions without filename + if (it==m_conditions.end()) + return RESULT_ERR_NOTFOUND; + condition = it->second; + types = types.substr(pos+1); + } + } if (types.length() == 0) types.append("r"); result_t result = RESULT_ERR_EOF; @@ -843,7 +849,7 @@ result_t MessageMap::addFromFile(vector::iterator& begin, const vector::iterator it = messages.begin(); it != messages.end(); it++) { Message* message = *it; if (result == RESULT_OK) { @@ -858,7 +864,6 @@ result_t MessageMap::addFromFile(vector::iterator& begin, const vector::iterator& it, const vector::iterator end, - vector< vector >* defaultsRows, map* conditions, const string& filename, + vector< vector >* defaultsRows, Condition* condition, const string& filename, DataFieldTemplates* templates, vector& messages); /** @@ -526,10 +526,14 @@ public: result_t add(Message* message); // @copydoc - virtual result_t addDefaultFromFile(vector< vector >& defaults, vector& row, vector::iterator& begin, const string& filename, unsigned int lineNo); + virtual result_t addDefaultFromFile(vector< vector >& defaults, vector& row, + vector::iterator& begin, string defaultDest, string defaultCircuit, + const string& filename, unsigned int lineNo); // @copydoc - virtual result_t addFromFile(vector::iterator& begin, const vector::iterator end, DataFieldTemplates* arg, vector< vector >* defaults, const string& filename, unsigned int lineNo); + virtual result_t addFromFile(vector::iterator& begin, const vector::iterator end, + DataFieldTemplates* arg, vector< vector >* defaults, + const string& filename, unsigned int lineNo); /** * Resolve all @a Condition instances.