added output of used-defined attributes, use const where appropriate, enhanced http global node, added base class AttributedItem

This commit is contained in:
john30
2017-04-09 16:38:40 +02:00
parent c56b0b518f
commit a19a38266a
20 changed files with 1052 additions and 882 deletions
+7 -7
View File
@@ -211,7 +211,7 @@ void GrabbedMessage::setLastData(MasterSymbolString& master, SlaveSymbolString&
* @param firstOnly whether to read only the first non-erroneous offset. * @param firstOnly whether to read only the first non-erroneous offset.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
bool decodeType(DataType* type, SymbolString *input, size_t length, bool decodeType(const DataType* type, SymbolString *input, size_t length,
size_t offsets, ostringstream& output, bool firstOnly = false) { size_t offsets, ostringstream& output, bool firstOnly = false) {
bool first = true; bool first = true;
string in = input->getStr(input->getDataOffset()); string in = input->getStr(input->getDataOffset());
@@ -225,7 +225,7 @@ bool decodeType(DataType* type, SymbolString *input, size_t length,
unsigned int value = 0; unsigned int value = 0;
if (type->readRawValue(*input, offset, length, value) == RESULT_OK) { if (type->readRawValue(*input, offset, length, value) == RESULT_OK) {
out.str(""); out.str("");
out << DataField::getDayName(reinterpret_cast<NumberDataType*>(type)->getMinValue()+value); out << DataField::getDayName(reinterpret_cast<const NumberDataType*>(type)->getMinValue()+value);
} }
} }
if (first) { if (first) {
@@ -288,8 +288,8 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
if (remain == 0) { if (remain == 0) {
return true; return true;
} }
for (map<string, DataType*>::const_iterator it = types->begin(); it != types->end(); it++) { for (auto it : *types) {
DataType* baseType = it->second; const DataType* baseType = it.second;
if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types
continue; continue;
} }
@@ -300,7 +300,7 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
} }
if (baseType->isAdjustableLength()) { if (baseType->isAdjustableLength()) {
for (size_t length = maxLength; length >= 1; length--) { for (size_t length = maxLength; length >= 1; length--) {
DataType* type = types->get(baseType->getId(), length); const DataType* type = types->get(baseType->getId(), length);
if (decodeType(type, input, length, remain-length, output, firstOnly)) { if (decodeType(type, input, length, remain-length, output, firstOnly)) {
if (firstOnly) { if (firstOnly) {
break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes break; // only a single offset with maximum length when adjustable maximum size is at least 8 bytes
@@ -1293,7 +1293,7 @@ void BusHandler::formatSeenInfo(ostringstream& output) {
} }
} }
} }
vector<string>& loadedFiles = m_messages->getLoadedFiles(address); const vector<string>& loadedFiles = m_messages->getLoadedFiles(address);
if (!loadedFiles.empty()) { if (!loadedFiles.empty()) {
bool first = true; bool first = true;
for (auto& loadedFile : loadedFiles) { for (auto& loadedFile : loadedFiles) {
@@ -1358,7 +1358,7 @@ void BusHandler::formatUpdateInfo(ostringstream& output) {
message->decodeLastData(output, OF_NAMES|OF_NUMERIC|OF_JSON|OF_SHORT, true); message->decodeLastData(output, OF_NAMES|OF_NUMERIC|OF_JSON|OF_SHORT, true);
} }
} }
vector<string>& loadedFiles = m_messages->getLoadedFiles(address); const vector<string>& loadedFiles = m_messages->getLoadedFiles(address);
if (!loadedFiles.empty()) { if (!loadedFiles.empty()) {
output << ",\"f\":["; output << ",\"f\":[";
bool first = true; bool first = true;
+7 -7
View File
@@ -73,7 +73,7 @@ class UserInfo {
* @param user the user name. * @param user the user name.
* @return whether the user exists. * @return whether the user exists.
*/ */
virtual bool hasUser(const string user) = 0; // abstract virtual bool hasUser(const string user) const = 0; // abstract
/** /**
* Check whether the secret string matches the one of the specified user. * Check whether the secret string matches the one of the specified user.
@@ -81,14 +81,14 @@ class UserInfo {
* @param secret the secret to check. * @param secret the secret to check.
* @return whether the secret string is valid. * @return whether the secret string is valid.
*/ */
virtual bool checkSecret(const string user, const string secret) = 0; // abstract virtual bool checkSecret(const string user, const string secret) const = 0; // abstract
/** /**
* Get the access levels associated with the specified user. * Get the access levels associated with the specified user.
* @param user the user name, or empty for default levels. * @param user the user name, or empty for default levels.
* @return the access levels separated by semicolon. * @return the access levels separated by semicolon.
*/ */
virtual string getLevels(const string user) = 0; // abstract virtual string getLevels(const string user) const = 0; // abstract
}; };
@@ -116,13 +116,13 @@ class DataHandler {
* Return whether this is a @a DataSink instance. * Return whether this is a @a DataSink instance.
* @return whether this is a @a DataSink instance. * @return whether this is a @a DataSink instance.
*/ */
virtual bool isDataSink() { return false; } virtual bool isDataSink() const { return false; }
/** /**
* Return whether this is a @a DataSource instance. * Return whether this is a @a DataSource instance.
* @return whether this is a @a DataSource instance. * @return whether this is a @a DataSource instance.
*/ */
virtual bool isDataSource() { return false; } virtual bool isDataSource() const { return false; }
}; };
@@ -146,7 +146,7 @@ class DataSink : virtual public DataHandler {
virtual ~DataSink() {} virtual ~DataSink() {}
// @copydoc // @copydoc
bool isDataSink() override { return true; } bool isDataSink() const override { return true; }
/** /**
* Notify the sink of an updated @a Message. * Notify the sink of an updated @a Message.
@@ -187,7 +187,7 @@ class DataSource : virtual public DataHandler {
virtual ~DataSource() {} virtual ~DataSource() {}
// @copydoc // @copydoc
bool isDataSource() override { return true; } bool isDataSource() const override { return true; }
protected: protected:
+2 -2
View File
@@ -884,9 +884,9 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
if (!message) { if (!message) {
return RESULT_ERR_NOTFOUND; return RESULT_ERR_NOTFOUND;
} }
SlaveSymbolString& data = message->getLastSlaveData(); const SlaveSymbolString& data = message->getLastSlaveData();
if (data.getDataSize() < 1+5+2+2) { if (data.getDataSize() < 1+5+2+2) {
logError(lf_main, "unable to load scan config %2.2x: slave part too short", address); logError(lf_main, "unable to load scan config %2.2x: slave part too short (%d)", address, data.getDataSize());
return RESULT_EMPTY; return RESULT_EMPTY;
} }
DataFieldSet* identFields = DataFieldSet::getIdentFields(); DataFieldSet* identFields = DataFieldSet::getIdentFields();
+33 -9
View File
@@ -41,7 +41,7 @@ using std::ifstream;
#define RECONNECT_MISSING_SIGNAL 60 #define RECONNECT_MISSING_SIGNAL 60
result_t UserList::getFieldMap(vector<string>& row, string& errorDescription) { result_t UserList::getFieldMap(vector<string>& row, string& errorDescription) const {
// name,secret,level[,level]* // name,secret,level[,level]*
if (row.empty()) { if (row.empty()) {
row.push_back("name"); row.push_back("name");
@@ -735,7 +735,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
if (srcAddress == SYN if (srcAddress == SYN
&& (message->getLastUpdateTime() + maxAge > now && (message->getLastUpdateTime() + maxAge > now
|| (message->isPassive() && message->getLastUpdateTime() != 0))) { || (message->isPassive() && message->getLastUpdateTime() != 0))) {
SlaveSymbolString& slave = message->getLastSlaveData(); const SlaveSymbolString& slave = message->getLastSlaveData();
logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str()); logNotice(lf_main, "hex read %s %s from cache", message->getCircuit().c_str(), message->getName().c_str());
return slave.getStr(); return slave.getStr();
} }
@@ -998,7 +998,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
getResultCode(ret)); getResultCode(ret));
return getResultCode(ret); return getResultCode(ret);
} }
dstAddress = message->getLastMasterData()[1]; dstAddress = message->getLastMasterData().dataAt(1);
ostringstream result; ostringstream result;
if (dstAddress == BROADCAST || isMaster(dstAddress)) { if (dstAddress == BROADCAST || isMaster(dstAddress)) {
logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(), logNotice(lf_main, "write %s %s: %s", message->getCircuit().c_str(), message->getName().c_str(),
@@ -1105,8 +1105,10 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
} }
} else if (args[argPos] == "-vv") { } else if (args[argPos] == "-vv") {
verbosity |= OF_NAMES|OF_UNITS; verbosity |= OF_NAMES|OF_UNITS;
} else if (args[argPos] == "-vvv" || args[argPos] == "-V") { } else if (args[argPos] == "-vvv") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS; verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS;
} else if (args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS|OF_ALL_ATTRS;
} else if (args[argPos] == "-f") { } else if (args[argPos] == "-f") {
configFormat = true; configFormat = true;
if (hexFormat) { if (hexFormat) {
@@ -1251,12 +1253,12 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
<< " / " << message->getLastSlaveData().getStr() << ")"; << " / " << message->getLastSlaveData().getStr() << ")";
} }
} }
if (verbosity == (OF_NAMES|OF_UNITS|OF_COMMENTS)) { if ((verbosity & (OF_NAMES|OF_UNITS|OF_COMMENTS)) == (OF_NAMES|OF_UNITS|OF_COMMENTS)) {
symbol_t dstAddress = message->getDstAddress(); symbol_t dstAddress = message->getDstAddress();
if (dstAddress != SYN) { if (dstAddress != SYN) {
snprintf(str, sizeof(str), "%02x", dstAddress); snprintf(str, sizeof(str), "%02x", dstAddress);
} else if (lastup != 0 && message->getLastMasterData().size() > 1) { } else if (lastup != 0 && message->getLastMasterData().size() > 1) {
snprintf(str, sizeof(str), "%02x", message->getLastMasterData()[1]); snprintf(str, sizeof(str), "%02x", message->getLastMasterData().dataAt(1));
} else { } else {
snprintf(str, sizeof(str), "any"); snprintf(str, sizeof(str), "any");
} }
@@ -1533,7 +1535,7 @@ string MainLoop::executeHelp() {
string MainLoop::executeGet(vector<string> &args, bool& connected) { string MainLoop::executeGet(vector<string> &args, bool& connected) {
result_t ret = RESULT_OK; result_t ret = RESULT_OK;
bool numeric = false, required = false; bool numeric = false, required = false, full = false;
OutputFormat verbosity = OF_NAMES; OutputFormat verbosity = OF_NAMES;
size_t argPos = 1; size_t argPos = 1;
string uri = args[argPos++]; string uri = args[argPos++];
@@ -1583,6 +1585,8 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
} }
} else if (qname == "numeric") { } else if (qname == "numeric") {
numeric = value.length() == 0 || value == "1"; numeric = value.length() == 0 || value == "1";
} else if (qname == "full") {
full = value.length() == 0 || value == "1";
} else if (qname == "required") { } else if (qname == "required") {
required = value.length() == 0 || value == "1"; required = value.length() == 0 || value == "1";
} else if (qname == "user") { } else if (qname == "user") {
@@ -1639,6 +1643,7 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
} }
lastCircuit = message->getCircuit(); lastCircuit = message->getCircuit();
result << "\n \"" << lastCircuit << "\": {"; result << "\n \"" << lastCircuit << "\": {";
// TODO add circuit specific values
first = true; first = true;
} }
if (first) { if (first) {
@@ -1652,7 +1657,8 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
result << ",\n \"zz\": \"" << setfill('0') << setw(2) << hex << static_cast<unsigned>(dstAddress) << "\""; result << ",\n \"zz\": \"" << setfill('0') << setw(2) << hex << static_cast<unsigned>(dstAddress) << "\"";
size_t pos = (size_t) result.tellp(); size_t pos = (size_t) result.tellp();
result << ",\n \"fields\": {"; result << ",\n \"fields\": {";
result_t dret = message->decodeLastData(result, verbosity | (numeric ? OF_NUMERIC : 0) | OF_JSON); result_t dret = message->decodeLastData(
result, verbosity | (numeric ? OF_NUMERIC : 0) | OF_JSON | (full ? OF_ALL_ATTRS : 0));
if (dret == RESULT_OK) { if (dret == RESULT_OK) {
result << "\n }"; result << "\n }";
} else { } else {
@@ -1671,7 +1677,25 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
result << "\n },"; result << "\n },";
} }
result << "\n \"global\": {"; result << "\n \"global\": {";
result << "\n \"signal\": " << (m_busHandler->hasSignal() ? "1" : "0"); result << "\n \"version\": \"" << PACKAGE_VERSION "." REVISION "\"";
if (!m_updateCheck.empty()) {
result << ",\n \"updatecheck\": \"" << m_updateCheck << "\"";
}
if (!user.empty()) {
result << ",\n \"user\": \"" << user << "\"";
}
string levels = getUserLevels(user);
if (!user.empty() || !levels.empty()) {
result << ",\n \"access\": \"" << levels << "\"";
}
result << ",\n \"signal\": " << (m_busHandler->hasSignal() ? "1" : "0");
if (m_busHandler->hasSignal()) {
result << ",\n \"symbolrate\": " << m_busHandler->getSymbolRate();
result << ",\n \"maxsymbolrate\": " << m_busHandler->getMaxSymbolRate();
}
result << ",\n \"reconnects\": " << m_reconnectCount;
result << ",\n \"masters\": " << m_busHandler->getMasterCount();
result << ",\n \"messages\": " << m_messages->size();
result << ",\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(maxLastUp); result << ",\n \"lastup\": " << setw(0) << dec << static_cast<unsigned>(maxLastUp);
result << "\n }"; result << "\n }";
result << "\n}"; result << "\n}";
+9 -5
View File
@@ -62,24 +62,28 @@ class UserList : public UserInfo, public MappedFileReader {
virtual ~UserList() {} virtual ~UserList() {}
// @copydoc // @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription) override; result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc // @copydoc
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows, result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override; string& errorDescription, const string filename, unsigned int lineNo) override;
// @copydoc // @copydoc
bool hasUser(const string user) override { bool hasUser(const string user) const override {
return m_userLevels.find(user) != m_userLevels.end(); return m_userLevels.find(user) != m_userLevels.end();
} }
// @copydoc // @copydoc
bool checkSecret(const string user, const string secret) override { bool checkSecret(const string user, const string secret) const override {
return m_userSecrets.find(user) != m_userSecrets.end() && m_userSecrets[user] == secret; auto it = m_userSecrets.find(user);
return it != m_userSecrets.end() && it->second == secret;
} }
// @copydoc // @copydoc
string getLevels(const string user) override { return m_userLevels[user]; } string getLevels(const string user) const override {
auto it = m_userLevels.find(user);
return it == m_userLevels.end() ? "" : it->second;
}
private: private:
/** the secret string by user name. */ /** the secret string by user name. */
+4 -4
View File
@@ -39,7 +39,7 @@ void contrib_tem_register() {
DataTypeList::getInstance()->add(new TemParamDataType("TEM_P")); DataTypeList::getInstance()->add(new TemParamDataType("TEM_P"));
} }
result_t TemParamDataType::derive(int divisor, size_t bitCount, NumberDataType* &derived) { result_t TemParamDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
if (divisor == 0) { if (divisor == 0) {
divisor = 1; divisor = 1;
} }
@@ -53,9 +53,9 @@ result_t TemParamDataType::derive(int divisor, size_t bitCount, NumberDataType*
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
result_t TemParamDataType::readSymbols(SymbolString& input, result_t TemParamDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) { ostringstream& output, OutputFormat outputFormat) const {
unsigned int value = 0; unsigned int value = 0;
result_t result = readRawValue(input, offset, length, value); result_t result = readRawValue(input, offset, length, value);
@@ -92,7 +92,7 @@ result_t TemParamDataType::readSymbols(SymbolString& input,
result_t TemParamDataType::writeSymbols(istringstream& input, result_t TemParamDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) { SymbolString& output, size_t* usedLength) const {
unsigned int value; unsigned int value;
int grp, num; int grp, num;
string token; string token;
+5 -5
View File
@@ -47,20 +47,20 @@ class TemParamDataType : public NumberDataType {
* @param id the type identifier. * @param id the type identifier.
*/ */
explicit TemParamDataType(const string id) explicit TemParamDataType(const string id)
: NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0) {} : NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0, NULL) {}
// @copydoc // @copydoc
result_t derive(int divisor, size_t bitCount, NumberDataType* &derived) override; result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const override;
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
}; };
/** /**
+4 -4
View File
@@ -54,7 +54,7 @@ class TestReader : public MappedFileReader {
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest) TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest), : MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
m_fields(NULL) {} m_fields(NULL) {}
result_t getFieldMap(vector<string>& row, string& errorDescription) override { result_t getFieldMap(vector<string>& row, string& errorDescription) const override {
if (row.empty()) { if (row.empty()) {
row.push_back("*name"); row.push_back("*name");
row.push_back("part"); row.push_back("part");
@@ -85,11 +85,11 @@ class TestReader : public MappedFileReader {
const bool m_isSet; const bool m_isSet;
const bool m_isMasterDest; const bool m_isMasterDest;
public: public:
DataField* m_fields; const DataField* m_fields;
}; };
int main() { int main() {
DataType* type = DataTypeList::getInstance()->get("TEM_P"); const DataType* type = DataTypeList::getInstance()->get("TEM_P");
if (type == NULL) { if (type == NULL) {
cout << "datatype not registered" << endl; cout << "datatype not registered" << endl;
return 1; return 1;
@@ -119,7 +119,7 @@ int main() {
string errorDescription; string errorDescription;
vector<string> row; vector<string> row;
templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row); templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
DataField* fields = NULL; const DataField* fields = NULL;
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) { for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i]; string check[5] = checks[i];
istringstream isstr(check[0]); istringstream isstr(check[0]);
+330 -267
View File
File diff suppressed because it is too large Load Diff
+199 -155
View File
@@ -91,18 +91,116 @@ string getDataFieldName(const size_t fieldId);
class DataFieldTemplates; class DataFieldTemplates;
class SingleDataField; class SingleDataField;
/**
* Base class for named items with optional named attributes.
*/
class AttributedItem {
protected:
/**
* Constructs a new instance.
* @param name the item name.
* @param attributes the additional named attributes.
*/
AttributedItem(const string name, const map<string, string>& attributes)
: m_name(name), m_attributes(attributes) {}
/**
* Constructs a new instance (without additional attributes).
* @param name the field name.
*/
explicit AttributedItem(const string name)
: m_name(name) {}
/**
* Destructor.
*/
virtual ~AttributedItem() {}
public:
/**
* Remove and return a certain value from a map.
* @param row the map to remove the value from.
* @param key the name of the value to remove.
* @return the named value from the map, or empty if not available.
*/
static const string pluck(map<string, string>& row, const string key);
/**
* Dump the @a string optionally embedded in @a TEXT_SEPARATOR to the output.
* @param output the @a ostream to dump to.
* @param str the @a string to dump.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
*/
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator = true);
/**
* Merge this instance's additional named attributes into the specified attributes.
* @param attributes the additional named attributes to merge in this instance's additional named attributes.
*/
void mergeAttributes(map<string, string>& attributes) const;
/**
* Dump the attribute optionally embedded in @a TEXT_SEPARATOR to the output.
* @param output the @a ostream to dump to.
* @param name the name of the attribute to dump.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
*/
void dumpAttribute(ostream& output, const string name, const bool prependFieldSeparator = true) const;
/**
* Append the attribute value to the output.
* @param output the @a ostringstream to append the formatted value to.
* @param outputFormat the @a OutputFormat options to use.
* @param name the name of the attribute to append.
* @param onlyIfNonEmpty true to append only if the value is not empty.
* @param prefix optional prefix to use (only for non-JSON output).
* @param suffix optional suffix to use (only for non-JSON output).
*/
void appendAttribute(ostringstream& output, OutputFormat outputFormat, const string name,
const bool onlyIfNonEmpty = true, const string prefix = "", const string suffix = "") const;
/**
* Get the item name.
* @return the item name.
*/
string getName() const { return m_name; }
/**
* Get a named attribute.
* @param name the name of the attribute.
* @return the named attribute value, or empty.
*/
string getAttribute(const string name) const;
protected:
/** the field name. */
const string m_name;
/** the additional named attributes. */
const map<string, string> m_attributes;
};
/** /**
* Base class for all kinds of data fields. * Base class for all kinds of data fields.
*/ */
class DataField { class DataField : public AttributedItem {
public: public:
/** /**
* Constructs a new instance. * Constructs a new instance.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param attributes the additional named attributes.
*/ */
DataField(const string name, const string comment) DataField(const string name, const map<string, string>& attributes)
: m_name(name), m_comment(comment) {} : AttributedItem(name, attributes) {}
/**
* Constructs a new instance (without additional attributes).
* @param name the field name.
*/
explicit DataField(const string name)
: AttributedItem(name) {}
/** /**
* Destructor. * Destructor.
@@ -113,7 +211,7 @@ class DataField {
* Clone this instance. * Clone this instance.
* @return a clone of this instance. * @return a clone of this instance.
*/ */
virtual DataField* clone() = 0; virtual const DataField* clone() const = 0;
/** /**
* Factory method for creating new instances. * Factory method for creating new instances.
@@ -129,18 +227,10 @@ class DataField {
* Note: the caller needs to free the created instance. * Note: the caller needs to free the created instance.
*/ */
static result_t create(vector< map<string, string> >& rows, string& errorDescription, static result_t create(vector< map<string, string> >& rows, string& errorDescription,
DataFieldTemplates* templates, DataField*& returnField, DataFieldTemplates* templates, const DataField*& returnField,
const bool isWriteMessage, const bool isWriteMessage,
const bool isTemplate, const bool isBroadcastOrMasterDestination, const bool isTemplate, const bool isBroadcastOrMasterDestination,
const size_t maxFieldLength = MAX_POS); const size_t maxFieldLength = MAX_POS);
/**
* Dump the @a string optionally embedded in @a TEXT_SEPARATOR to the output.
* @param output the @a ostream to dump to.
* @param str the @a string to dump.
* @param prependFieldSeparator whether to start with a @a FIELD_SEPARATOR.
*/
static void dumpString(ostream& output, const string str, const bool prependFieldSeparator = true);
/** /**
* Return the name of the specified day. * Return the name of the specified day.
@@ -155,42 +245,33 @@ class DataField {
* @param maxLength the maximum length for calculating remainder of input. * @param maxLength the maximum length for calculating remainder of input.
* @return the length of this field (or contained fields) in bytes. * @return the length of this field (or contained fields) in bytes.
*/ */
virtual size_t getLength(PartType partType, size_t maxLength = MAX_LEN) = 0; virtual size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const = 0;
/** /**
* Derive a new @a DataField from this field. * Derive a new @a DataField from this field.
* @param name the field name, or empty to use this fields name. * @param name the field name, or empty to use this fields name.
* @param comment the field comment, or empty to use this fields comment. * @param attributes the additional named attributes to override.
* @param unit the value unit, or empty to use this fields unit (if applicable).
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable). * @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable).
* @param values the value=text assignments, or empty to use this fields assignments (if applicable). * @param values the value=text assignments, or empty to use this fields assignments (if applicable).
* @param fields the @a vector to which created @a SingleDataField instances shall be added. * @param fields the @a vector to which created @a SingleDataField instances shall be added.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t derive(string name, string comment, virtual result_t derive(const string name, map<string, string> attributes, const PartType partType,
string unit, const PartType partType, int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const = 0;
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) = 0;
/** /**
* Get the specified field name. * Get the specified field name.
* @param fieldIndex the index of the field, or -1 for this. * @param fieldIndex the index of the field, or -1 for this.
* @return the field name, or the index as string if not unique or not available. * @return the field name, or the index as string if not unique or not available.
*/ */
virtual string getName(ssize_t fieldIndex = -1) { return m_name; } virtual string getName(const ssize_t fieldIndex = -1) const { return m_name; }
/**
* Get the field comment.
* @return the field comment.
*/
string getComment() const { return m_comment; }
/** /**
* Dump the field settings to the output. * Dump the field settings to the output.
* @param output the @a ostream to dump to. * @param output the @a ostream to dump to.
*/ */
virtual void dump(ostream& output) = 0; virtual void dump(ostream& output) const = 0;
/** /**
* Return whether the field is available. * Return whether the field is available.
@@ -198,7 +279,7 @@ class DataField {
* @param numeric true for a numeric field, false for a string field. * @param numeric true for a numeric field, false for a string field.
* @return true if the field is available. * @return true if the field is available.
*/ */
virtual bool hasField(const char* fieldName, bool numeric) = 0; virtual bool hasField(const char* fieldName, bool numeric) const = 0;
/** /**
* Reads the numeric value from the @a SymbolString. * Reads the numeric value from the @a SymbolString.
@@ -212,8 +293,8 @@ class DataField {
* not match or ignored, or due to @a fieldName or @a fieldIndex), * not match or ignored, or due to @a fieldName or @a fieldIndex),
* or an error code. * or an error code.
*/ */
virtual result_t read(SymbolString& data, size_t offset, virtual result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) = 0; unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
/** /**
* Reads the value from the @a SymbolString. * Reads the value from the @a SymbolString.
@@ -229,9 +310,9 @@ class DataField {
* or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex), * or @a RESULT_EMPTY if the field was skipped (either ignored or due to @a fieldName or @a fieldIndex),
* or an error code. * or an error code.
*/ */
virtual result_t read(SymbolString& data, size_t offset, virtual result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1, ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) = 0; bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
/** /**
* Writes the value to the master or slave @a SymbolString. * Writes the value to the master or slave @a SymbolString.
@@ -243,15 +324,7 @@ class DataField {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t write(istringstream& input, SymbolString& data, virtual result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) = 0; size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const = 0;
protected:
/** the field name. */
const string m_name;
/** the field comment. */
const string m_comment;
}; };
@@ -263,18 +336,15 @@ class SingleDataField : public DataField {
/** /**
* Constructs a new instance. * Constructs a new instance.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param attributes the additional named attributes.
* @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
*/ */
SingleDataField(const string name, const string comment, SingleDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const string unit, DataType* dataType, const PartType partType, const PartType partType, const size_t length)
const size_t length) : DataField(name, attributes),
: DataField(name, comment), m_partType(partType), m_dataType(dataType), m_length(length) {}
m_unit(unit), m_dataType(dataType), m_partType(partType),
m_length(length) {}
/** /**
* Destructor. * Destructor.
@@ -282,16 +352,15 @@ class SingleDataField : public DataField {
virtual ~SingleDataField() {} virtual ~SingleDataField() {}
// @copydoc // @copydoc
SingleDataField* clone() override; const SingleDataField* clone() const override;
/** /**
* Factory method for creating a new @a SingleDataField instance derived from a base type. * Factory method for creating a new @a SingleDataField instance derived from a base type.
* @param id the ID string (excluding optional length suffix).
* @param length the base type length, or 0 for default, or @a REMAIN_LEN for remainder within same message part.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param attributes the additional named attributes.
* @param unit the value unit.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param dataType the @a DataType instance.
* @param length the base type length, or 0 for default, or @a REMAIN_LEN for remainder within same message part.
* @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable). * @param divisor the extra divisor (negative for reciprocal) to apply on the value, or 1 for none (if applicable).
* @param values the value=text assignments. * @param values the value=text assignments.
* @param constantValue the constant value as string, or empty. * @param constantValue the constant value as string, or empty.
@@ -300,16 +369,9 @@ class SingleDataField : public DataField {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
* Note: the caller needs to free the created instance. * Note: the caller needs to free the created instance.
*/ */
static result_t create(const string id, const size_t length, static result_t create(const string name, const map<string, string>& attributes, const DataType* dataType,
const string name, const string comment, const string unit, const PartType partType, const size_t length, int divisor, map<unsigned int, string> values,
const PartType partType, int divisor, map<unsigned int, string> values, const string constantValue, const bool verifyValue, SingleDataField* &returnField);
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
/**
* Get the value unit.
* @return the value unit.
*/
string getUnit() const { return m_unit; }
/** /**
* Get whether this field is ignored. * Get whether this field is ignored.
@@ -324,13 +386,11 @@ class SingleDataField : public DataField {
PartType getPartType() const { return m_partType; } PartType getPartType() const { return m_partType; }
// @copydoc // @copydoc
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) override; size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
// @copydoc // @copydoc
result_t derive(string name, string comment, result_t derive(const string name, map<string, string> attributes, const PartType partType,
string unit, const PartType partType, int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
/** /**
* Get whether this field uses a full byte offset. * Get whether this field uses a full byte offset.
@@ -338,26 +398,26 @@ class SingleDataField : public DataField {
* @return @p true if this field uses a full byte offset, @p false if this field * @return @p true if this field uses a full byte offset, @p false if this field
* only consumes a part of a byte and a subsequent field may re-use the same offset. * only consumes a part of a byte and a subsequent field may re-use the same offset.
*/ */
bool hasFullByteOffset(bool after); bool hasFullByteOffset(bool after) const;
// @copydoc // @copydoc
void dump(ostream& output) override; void dump(ostream& output) const override;
// @copydoc // @copydoc
bool hasField(const char* fieldName, bool numeric) override; bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc // @copydoc
result_t read(SymbolString& data, size_t offset, result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) override; unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc // @copydoc
result_t read(SymbolString& data, size_t offset, result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1, ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) override; bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc // @copydoc
result_t write(istringstream& input, SymbolString& data, result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) override; size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
protected: protected:
@@ -369,9 +429,9 @@ class SingleDataField : public DataField {
* @param outputFormat the @a OutputFormat options to use. * @param outputFormat the @a OutputFormat options to use.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t readSymbols(SymbolString& input, virtual result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t offset,
ostringstream& output, OutputFormat outputFormat); ostringstream& output, OutputFormat outputFormat) const;
/** /**
* Internal method for writing the field to a @a SymbolString. * Internal method for writing the field to a @a SymbolString.
@@ -382,18 +442,15 @@ class SingleDataField : public DataField {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t writeSymbols(istringstream& input, virtual result_t writeSymbols(istringstream& input,
const size_t offset, const size_t offset,
SymbolString& output, size_t* usedLength); SymbolString& output, size_t* usedLength) const;
/** the value unit. */
const string m_unit;
/** the data type definition. */
DataType* m_dataType;
/** the message part in which the field is stored. */ /** the message part in which the field is stored. */
const PartType m_partType; const PartType m_partType;
/** the data type definition. */
const DataType* m_dataType;
/** the number of symbols in the message part in which the field is stored. */ /** the number of symbols in the message part in which the field is stored. */
const size_t m_length; const size_t m_length;
}; };
@@ -407,17 +464,15 @@ class ValueListDataField : public SingleDataField {
/** /**
* Constructs a new instance. * Constructs a new instance.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param attributes the additional named attributes.
* @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
* @param values the value=text assignments. * @param values the value=text assignments.
*/ */
ValueListDataField(const string name, const string comment, ValueListDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const string unit, NumberDataType* dataType, const PartType partType, const PartType partType, const size_t length, const map<unsigned int, string> values)
const size_t length, const map<unsigned int, string> values) : SingleDataField(name, attributes, dataType, partType, length),
: SingleDataField(name, comment, unit, dataType, partType, length),
m_values(values) {} m_values(values) {}
/** /**
@@ -426,31 +481,29 @@ class ValueListDataField : public SingleDataField {
virtual ~ValueListDataField() {} virtual ~ValueListDataField() {}
// @copydoc // @copydoc
ValueListDataField* clone() override; const ValueListDataField* clone() const override;
// @copydoc // @copydoc
result_t derive(string name, string comment, result_t derive(const string name, map<string, string> attributes, const PartType partType,
string unit, const PartType partType, int divisor, int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
// @copydoc // @copydoc
void dump(ostream& output) override; void dump(ostream& output) const override;
protected: protected:
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, const size_t offset, result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, const size_t offset, result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
private: private:
/** the value=text assignments. */ /** the value=text assignments. */
map<unsigned int, string> m_values; const map<unsigned int, string> m_values;
}; };
@@ -462,18 +515,16 @@ class ConstantDataField : public SingleDataField {
/** /**
* Constructs a new instance. * Constructs a new instance.
* @param name the field name. * @param name the field name.
* @param comment the field comment. * @param attributes the additional named attributes.
* @param unit the value unit.
* @param dataType the data type definition. * @param dataType the data type definition.
* @param partType the message part in which the field is stored. * @param partType the message part in which the field is stored.
* @param length the number of symbols in the message part in which the field is stored. * @param length the number of symbols in the message part in which the field is stored.
* @param value the constant value. * @param value the constant value.
* @param verify whether to verify the read value against the constant value. * @param verify whether to verify the read value against the constant value.
*/ */
ConstantDataField(const string name, const string comment, ConstantDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const string unit, DataType* dataType, const PartType partType, const PartType partType, const size_t length, const string value, const bool verify)
const size_t length, const string value, const bool verify) : SingleDataField(name, attributes, dataType, partType, length),
: SingleDataField(name, comment, unit, dataType, partType, length),
m_value(value), m_verify(verify) {} m_value(value), m_verify(verify) {}
/** /**
@@ -482,26 +533,24 @@ class ConstantDataField : public SingleDataField {
virtual ~ConstantDataField() {} virtual ~ConstantDataField() {}
// @copydoc // @copydoc
ConstantDataField* clone() override; const ConstantDataField* clone() const override;
// @copydoc // @copydoc
result_t derive(string name, string comment, result_t derive(const string name, map<string, string> attributes, const PartType partType,
string unit, const PartType partType, int divisor, int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
// @copydoc // @copydoc
void dump(ostream& output) override; void dump(ostream& output) const override;
protected: protected:
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, const size_t offset, result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, const size_t offset, result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
private: private:
@@ -533,16 +582,13 @@ class DataFieldSet : public DataField {
/** /**
* Constructs a new instance. * Constructs a new instance.
* @param name the field name. * @param name the field name.
* @param comment the field comment.
* @param fields the @a vector of @a SingleDataField instances part of this set. * @param fields the @a vector of @a SingleDataField instances part of this set.
*/ */
DataFieldSet(const string name, const string comment, DataFieldSet(const string name, const vector<const SingleDataField*> fields)
const vector<SingleDataField*> fields) : DataField(name), m_fields(fields) {
: DataField(name, comment), m_fields(fields) {
bool uniqueNames = true; bool uniqueNames = true;
map<string, string> names; map<string, string> names;
for (vector<SingleDataField*>::const_iterator it = fields.begin(); it != fields.end(); it++) { for (auto field : fields) {
SingleDataField* field = *it;
if (field->isIgnored()) { if (field->isIgnored()) {
continue; continue;
} }
@@ -562,31 +608,29 @@ class DataFieldSet : public DataField {
virtual ~DataFieldSet(); virtual ~DataFieldSet();
// @copydoc // @copydoc
DataFieldSet* clone() override; const DataFieldSet* clone() const override;
// @copydoc // @copydoc
size_t getLength(PartType partType, size_t maxLength = MAX_LEN) override; size_t getLength(PartType partType, size_t maxLength = MAX_LEN) const override;
// @copydoc // @copydoc
string getName(ssize_t fieldIndex = -1) override; string getName(const ssize_t fieldIndex = -1) const override;
// @copydoc // @copydoc
result_t derive(string name, string comment, result_t derive(const string name, map<string, string> attributes, const PartType partType,
string unit, const PartType partType, int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
/** /**
* Returns the @a SingleDataField at the specified index. * Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return. * @param index the index of the @a SingleDataField to return.
* @return the @a SingleDataField at the specified index, or NULL. * @return the @a SingleDataField at the specified index, or NULL.
*/ */
SingleDataField* operator[](const size_t index) { /*SingleDataField* operator[](const size_t index) {
if (index >= m_fields.size()) { if (index >= m_fields.size()) {
return NULL; return NULL;
} }
return m_fields[index]; return m_fields[index];
} }*/
/** /**
* Returns the @a SingleDataField at the specified index. * Returns the @a SingleDataField at the specified index.
@@ -607,23 +651,23 @@ class DataFieldSet : public DataField {
size_t size() const { return m_fields.size(); } size_t size() const { return m_fields.size(); }
// @copydoc // @copydoc
bool hasField(const char* fieldName, bool numeric) override; bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc // @copydoc
void dump(ostream& output) override; void dump(ostream& output) const override;
// @copydoc // @copydoc
result_t read(SymbolString& data, size_t offset, result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) override; unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc // @copydoc
result_t read(SymbolString& data, size_t offset, result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1, ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) override; bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc // @copydoc
result_t write(istringstream& input, SymbolString& data, result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) override; size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const override;
private: private:
@@ -631,7 +675,7 @@ class DataFieldSet : public DataField {
static DataFieldSet* s_identFields; static DataFieldSet* s_identFields;
/** the @a vector of @a SingleDataField instances part of this set. */ /** the @a vector of @a SingleDataField instances part of this set. */
vector<SingleDataField*> m_fields; const vector<const SingleDataField*> m_fields;
/** whether all fields have a unique name. */ /** whether all fields have a unique name. */
bool m_uniqueNames; bool m_uniqueNames;
@@ -674,14 +718,14 @@ class DataFieldTemplates : public MappedFileReader {
* @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(DataField* field, string name = "", bool replace = false); result_t add(const DataField* field, string name = "", bool replace = false);
// @copydoc // @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription) override; result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc // @copydoc
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows, result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override; string& errorDescription, const string filename, unsigned int lineNo) override;
/** /**
* Gets the template @a DataField instance with the specified name. * Gets the template @a DataField instance with the specified name.
@@ -689,12 +733,12 @@ class DataFieldTemplates : public MappedFileReader {
* @return the template @a DataField instance, or NULL. * @return the template @a DataField instance, or NULL.
* Note: the caller may not free the returned instance. * Note: the caller may not free the returned instance.
*/ */
DataField* get(string name); const DataField* get(string name) const;
private: private:
/** the known template @a DataField instances by name. */ /** the known template @a DataField instances by name. */
map<string, DataField*> m_fieldsByName; map<string, const DataField*> m_fieldsByName;
}; };
} // namespace ebusd } // namespace ebusd
+68 -67
View File
@@ -58,14 +58,14 @@ bool DataType::dump(ostream& output, const size_t length, const bool appendSepar
} }
result_t StringDataType::readRawValue(SymbolString& input, const size_t offset, result_t StringDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) { const size_t length, unsigned int& value) const {
return RESULT_EMPTY; return RESULT_EMPTY;
} }
result_t StringDataType::readSymbols(SymbolString& input, result_t StringDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) { ostringstream& output, OutputFormat outputFormat) const {
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
symbol_t symbol; symbol_t symbol;
@@ -116,7 +116,7 @@ result_t StringDataType::readSymbols(SymbolString& input,
result_t StringDataType::writeSymbols(istringstream& input, result_t StringDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length, size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) { SymbolString& output, size_t* usedLength) const {
size_t start = 0, count = length; size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ); bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1; int incr = 1;
@@ -196,14 +196,14 @@ result_t StringDataType::writeSymbols(istringstream& input,
} }
result_t DateTimeDataType::readRawValue(SymbolString& input, const size_t offset, result_t DateTimeDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) { const size_t length, unsigned int& value) const {
return RESULT_EMPTY; return RESULT_EMPTY;
} }
result_t DateTimeDataType::readSymbols(SymbolString& input, result_t DateTimeDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) { ostringstream& output, OutputFormat outputFormat) const {
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
symbol_t symbol, last = 0, hour = 0; symbol_t symbol, last = 0, hour = 0;
@@ -335,7 +335,7 @@ result_t DateTimeDataType::readSymbols(SymbolString& input,
result_t DateTimeDataType::writeSymbols(istringstream& input, result_t DateTimeDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length, size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) { SymbolString& output, size_t* usedLength) const {
size_t start = 0, count = length; size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ); bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1; int incr = 1;
@@ -527,7 +527,7 @@ bool NumberDataType::dump(ostream& output, size_t length, const bool appendSepar
return false; return false;
} }
result_t NumberDataType::derive(int divisor, size_t bitCount, NumberDataType* &derived) { result_t NumberDataType::derive(int divisor, size_t bitCount, const NumberDataType* &derived) const {
if (divisor == 0) { if (divisor == 0) {
divisor = 1; divisor = 1;
} }
@@ -570,19 +570,18 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, NumberDataType* &d
} }
if (m_bitCount < 8) { if (m_bitCount < 8) {
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement, derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
m_firstBit, divisor); m_firstBit, divisor, m_baseType ? m_baseType : this);
} else { } else {
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement, derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
m_minValue, m_maxValue, divisor); m_minValue, m_maxValue, divisor, m_baseType ? m_baseType : this);
} }
derived->m_baseType = m_baseType ? m_baseType : this;
DataTypeList::getInstance()->addCleanup(derived); DataTypeList::getInstance()->addCleanup(derived);
return RESULT_OK; return RESULT_OK;
} }
result_t NumberDataType::readRawValue(SymbolString& input, result_t NumberDataType::readRawValue(const SymbolString& input,
size_t offset, const size_t length, size_t offset, const size_t length,
unsigned int& value) { unsigned int& value) const {
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
symbol_t symbol; symbol_t symbol;
@@ -629,9 +628,9 @@ result_t NumberDataType::readRawValue(SymbolString& input,
return RESULT_OK; return RESULT_OK;
} }
result_t NumberDataType::readSymbols(SymbolString& input, result_t NumberDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) { ostringstream& output, OutputFormat outputFormat) const {
unsigned int value = 0; unsigned int value = 0;
int signedValue; int signedValue;
@@ -743,7 +742,7 @@ result_t NumberDataType::readSymbols(SymbolString& input,
result_t NumberDataType::writeRawValue(unsigned int value, result_t NumberDataType::writeRawValue(unsigned int value,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) { SymbolString& output, size_t* usedLength) const {
size_t start = 0, count = length; size_t start = 0, count = length;
int incr = 1; int incr = 1;
symbol_t symbol; symbol_t symbol;
@@ -789,7 +788,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
result_t NumberDataType::writeSymbols(istringstream& input, result_t NumberDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) { SymbolString& output, size_t* usedLength) const {
unsigned int value; unsigned int value;
const char* str = input.str().c_str(); const char* str = input.str().c_str();
@@ -906,8 +905,8 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
DataTypeList::DataTypeList() { DataTypeList::DataTypeList() {
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
// unsigned decimal in BCD, 0000 - 9999 (fixed length) // unsigned decimal in BCD, 0000 - 9999 (fixed length)
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1)); add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1, NULL));
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254 add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1, NULL)); // unsigned integer, 0 - 254
add(new StringDataType("IGN", MAX_LEN*8, IGN|ADJ, 0)); // >= 1 byte ignored data add(new StringDataType("IGN", MAX_LEN*8, IGN|ADJ, 0)); // >= 1 byte ignored data
// >= 1 byte character string filled up with 0x00 (null terminated string) // >= 1 byte character string filled up with 0x00 (null terminated string)
add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0)); add(new StringDataType("NTS", MAX_LEN*8, ADJ, 0));
@@ -945,56 +944,56 @@ DataTypeList::DataTypeList() {
add(new DateTimeDataType("TTH", 6, 0, 0, false, true, 30)); add(new DateTimeDataType("TTH", 6, 0, 0, false, true, 30));
// truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer) // truncated time (only multiple of 15 minutes), 00:00 - 24:00 (minutes div 15 + hour * 4 as integer)
add(new DateTimeDataType("TTQ", 7, 0, 0, false, true, 15)); add(new DateTimeDataType("TTQ", 7, 0, 0, false, true, 15));
add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type] add(new NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1, NULL)); // weekday, "Mon" - "Sun" (0x00 - 0x06) [eBUS type]
add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type] add(new NumberDataType("HDY", 8, DAY, 0x00, 1, 7, 1, NULL)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1)); // unsigned decimal in BCD, 0 - 99 add(new NumberDataType("BCD", 8, BCD, 0xff, 0, 99, 1, NULL)); // unsigned decimal in BCD, 0 - 99
add(new NumberDataType("BCD", 16, BCD, 0xffff, 0, 9999, 1)); // unsigned decimal in BCD, 0 - 9999 add(new NumberDataType("BCD", 16, BCD, 0xffff, 0, 9999, 1, NULL)); // unsigned decimal in BCD, 0 - 9999
add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1)); // unsigned decimal in BCD, 0 - 999999 add(new NumberDataType("BCD", 24, BCD, 0xffffff, 0, 999999, 1, NULL)); // unsigned decimal in BCD, 0 - 999999
add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1)); // unsigned decimal in BCD, 0 - 99999999 add(new NumberDataType("BCD", 32, BCD, 0xffffffff, 0, 99999999, 1, NULL)); // unsigned decimal in BCD, 0 - 99999999
add(new NumberDataType("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1)); // unsigned decimal in HCD, 0 - 99999999 add(new NumberDataType("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1, NULL)); // unsigned decimal in HCD, 0 - 99999999
add(new NumberDataType("HCD", 8, HCD|BCD|REQ, 0, 0, 99, 1)); // unsigned decimal in HCD, 0 - 99 add(new NumberDataType("HCD", 8, HCD|BCD|REQ, 0, 0, 99, 1, NULL)); // unsigned decimal in HCD, 0 - 99
add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // unsigned decimal in HCD, 0 - 9999 add(new NumberDataType("HCD", 16, HCD|BCD|REQ, 0, 0, 9999, 1, NULL)); // unsigned decimal in HCD, 0 - 9999
add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1)); // unsigned decimal in HCD, 0 - 999999 add(new NumberDataType("HCD", 24, HCD|BCD|REQ, 0, 0, 999999, 1, NULL)); // unsigned decimal in HCD, 0 - 999999
add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127 add(new NumberDataType("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1, NULL)); // signed integer, -127 - +127
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127 add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1, NULL)); // signed integer, -127 - +127
// unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff) // unsigned number (fraction 1/2), 0 - 100 (0x00 - 0xc8, replacement 0xff)
add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2)); add(new NumberDataType("D1C", 8, 0, 0xff, 0x00, 0xc8, 2, NULL));
// signed number (fraction 1/256), -127.99 - +127.99 // signed number (fraction 1/256), -127.99 - +127.99
add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256)); add(new NumberDataType("D2B", 16, SIG, 0x8000, 0x8001, 0x7fff, 256, NULL));
// signed number (fraction 1/16), -2047.9 - +2047.9 // signed number (fraction 1/16), -2047.9 - +2047.9
add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16)); add(new NumberDataType("D2C", 16, SIG, 0x8000, 0x8001, 0x7fff, 16, NULL));
// signed number (fraction 1/1000), -32.767 - +32.767, little endian // signed number (fraction 1/1000), -32.767 - +32.767, little endian
add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000)); add(new NumberDataType("FLT", 16, SIG, 0x8000, 0x8001, 0x7fff, 1000, NULL));
// signed number (fraction 1/1000), -32.767 - +32.767, big endian // signed number (fraction 1/1000), -32.767 - +32.767, big endian
add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000)); add(new NumberDataType("FLR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1000, NULL));
// signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), little endian
add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1)); add(new NumberDataType("EXP", 32, SIG|EXP, 0x7f800000, 0x00000000, 0xffffffff, 1, NULL));
// signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian // signed number (IEEE 754 binary32: 1 bit sign, 8 bits exponent, 23 bits significand), big endian
add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1)); add(new NumberDataType("EXR", 32, SIG|EXP|REV, 0x7f800000, 0x00000000, 0xffffffff, 1, NULL));
// unsigned integer, 0 - 65534, little endian // unsigned integer, 0 - 65534, little endian
add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1)); add(new NumberDataType("UIN", 16, 0, 0xffff, 0, 0xfffe, 1, NULL));
// unsigned integer, 0 - 65534, big endian // unsigned integer, 0 - 65534, big endian
add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1)); add(new NumberDataType("UIR", 16, REV, 0xffff, 0, 0xfffe, 1, NULL));
// signed integer, -32767 - +32767, little endian // signed integer, -32767 - +32767, little endian
add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1)); add(new NumberDataType("SIN", 16, SIG, 0x8000, 0x8001, 0x7fff, 1, NULL));
// signed integer, -32767 - +32767, big endian // signed integer, -32767 - +32767, big endian
add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1)); add(new NumberDataType("SIR", 16, SIG|REV, 0x8000, 0x8001, 0x7fff, 1, NULL));
// unsigned 3 bytes int, 0 - 16777214, little endian // unsigned 3 bytes int, 0 - 16777214, little endian
add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1)); add(new NumberDataType("U3N", 24, 0, 0xffffff, 0, 0xfffffe, 1, NULL));
// unsigned 3 bytes int, 0 - 16777214, big endian // unsigned 3 bytes int, 0 - 16777214, big endian
add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1)); add(new NumberDataType("U3R", 24, REV, 0xffffff, 0, 0xfffffe, 1, NULL));
// signed 3 bytes int, -8388607 - +8388607, little endian // signed 3 bytes int, -8388607 - +8388607, little endian
add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1)); add(new NumberDataType("S3N", 24, SIG, 0x800000, 0x800001, 0xffffff, 1, NULL));
// signed 3 bytes int, -8388607 - +8388607, big endian // signed 3 bytes int, -8388607 - +8388607, big endian
add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1)); add(new NumberDataType("S3R", 24, SIG|REV, 0x800000, 0x800001, 0xffffff, 1, NULL));
// unsigned integer, 0 - 4294967294, little endian // unsigned integer, 0 - 4294967294, little endian
add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1)); add(new NumberDataType("ULG", 32, 0, 0xffffffff, 0, 0xfffffffe, 1, NULL));
// unsigned integer, 0 - 4294967294, big endian // unsigned integer, 0 - 4294967294, big endian
add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1)); add(new NumberDataType("ULR", 32, REV, 0xffffffff, 0, 0xfffffffe, 1, NULL));
// signed integer, -2147483647 - +2147483647, little endian // signed integer, -2147483647 - +2147483647, little endian
add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1)); add(new NumberDataType("SLG", 32, SIG, 0x80000000, 0x80000001, 0xffffffff, 1, NULL));
// signed integer, -2147483647 - +2147483647, big endian // signed integer, -2147483647 - +2147483647, big endian
add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1)); add(new NumberDataType("SLR", 32, SIG|REV, 0x80000000, 0x80000001, 0xffffffff, 1, NULL));
add(new NumberDataType("BI0", 7, ADJ|REQ, 0, 0, 1)); // bit 0 (up to 7 bits until bit 6) add(new NumberDataType("BI0", 7, ADJ|REQ, 0, 0, 1)); // bit 0 (up to 7 bits until bit 6)
add(new NumberDataType("BI1", 7, ADJ|REQ, 0, 1, 1)); // bit 1 (up to 7 bits until bit 7) add(new NumberDataType("BI1", 7, ADJ|REQ, 0, 1, 1)); // bit 1 (up to 7 bits until bit 7)
add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7) add(new NumberDataType("BI2", 6, ADJ|REQ, 0, 2, 1)); // bit 2 (up to 6 bits until bit 7)
@@ -1010,21 +1009,20 @@ DataTypeList* DataTypeList::getInstance() {
} }
void DataTypeList::clear() { void DataTypeList::clear() {
for (list<DataType*>::iterator it = m_cleanupTypes.begin(); it != m_cleanupTypes.end(); it++) { for (auto& it : m_cleanupTypes) {
delete *it; delete it;
} }
m_cleanupTypes.clear(); m_cleanupTypes.clear();
m_typesByIdLength.clear(); m_typesByIdLength.clear();
m_typesById.clear(); m_typesById.clear();
} }
result_t DataTypeList::add(DataType* dataType) { result_t DataTypeList::add(const DataType* dataType) {
if (!dataType->isAdjustableLength()) { if (!dataType->isAdjustableLength()) {
ostringstream str; ostringstream str;
size_t bitCount = dataType->getBitCount(); size_t bitCount = dataType->getBitCount();
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount); str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount);
map<string, DataType*>::iterator it = m_typesByIdLength.find(str.str()); if (m_typesByIdLength.find(str.str()) != m_typesByIdLength.end()) {
if (it != m_typesByIdLength.end()) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key return RESULT_ERR_DUPLICATE_NAME; // duplicate key
} }
m_typesByIdLength[str.str()] = dataType; m_typesByIdLength[str.str()] = dataType;
@@ -1040,20 +1038,23 @@ result_t DataTypeList::add(DataType* dataType) {
return RESULT_OK; return RESULT_OK;
} }
DataType* DataTypeList::get(const string id, const size_t length) { const DataType* DataTypeList::get(const string id, const size_t length) const {
DataType* dataType = NULL;
if (length > 0) { if (length > 0) {
ostringstream str; ostringstream str;
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length); str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
dataType = m_typesByIdLength[str.str()]; auto it = m_typesByIdLength.find(str.str());
} if (it != m_typesByIdLength.end()) {
if (!dataType) { return it->second;
dataType = m_typesById[id];
if (dataType && length > 0 && !dataType->isAdjustableLength()) {
return NULL;
} }
} }
return dataType; auto it = m_typesById.find(id);
if (it == m_typesById.end()) {
return NULL;
}
if (length > 0 && !it->second->isAdjustableLength()) {
return NULL;
}
return it->second;
} }
} // namespace ebusd } // namespace ebusd
+41 -35
View File
@@ -100,6 +100,9 @@ typedef int OutputFormat;
/** bit flag for @a OutputFormat: short format (only name and value, no indentation). */ /** bit flag for @a OutputFormat: short format (only name and value, no indentation). */
#define OF_SHORT 0x20 #define OF_SHORT 0x20
/** bit flag for @a OutputFormat: include all attributes. */
#define OF_ALL_ATTRS 0x40
/** the message part in which a data field is stored. */ /** the message part in which a data field is stored. */
enum PartType { enum PartType {
pt_any, //!< stored in any data (master or slave) pt_any, //!< stored in any data (master or slave)
@@ -225,9 +228,9 @@ class DataType {
* @param value the variable in which to store the numeric raw value. * @param value the variable in which to store the numeric raw value.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t readRawValue(SymbolString& input, virtual result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
unsigned int& value) = 0; unsigned int& value) const = 0;
/** /**
* Internal method for reading the field from a @a SymbolString. * Internal method for reading the field from a @a SymbolString.
@@ -238,9 +241,9 @@ class DataType {
* @param outputFormat the @a OutputFormat options to use. * @param outputFormat the @a OutputFormat options to use.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t readSymbols(SymbolString& input, virtual result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) = 0; ostringstream& output, OutputFormat outputFormat) const = 0;
/** /**
* Internal method for writing the field to a @a SymbolString. * Internal method for writing the field to a @a SymbolString.
@@ -253,7 +256,7 @@ class DataType {
*/ */
virtual result_t writeSymbols(istringstream& input, virtual result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) = 0; SymbolString& output, size_t* usedLength) const = 0;
protected: protected:
@@ -295,19 +298,19 @@ class StringDataType : public DataType {
virtual ~StringDataType() {} virtual ~StringDataType() {}
// @copydoc // @copydoc
result_t readRawValue(SymbolString& input, result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
unsigned int& value) override; unsigned int& value) const override;
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
private: private:
@@ -357,19 +360,19 @@ class DateTimeDataType : public DataType {
int16_t getResolution() const { return m_resolution; } int16_t getResolution() const { return m_resolution; }
// @copydoc // @copydoc
result_t readRawValue(SymbolString& input, result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
unsigned int& value) override; unsigned int& value) const override;
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
private: private:
@@ -398,11 +401,13 @@ class NumberDataType : public DataType {
* @param minValue the minimum raw value. * @param minValue the minimum raw value.
* @param maxValue the maximum raw value. * @param maxValue the maximum raw value.
* @param divisor the divisor (negative for reciprocal). * @param divisor the divisor (negative for reciprocal).
* @param baseType the base @a NumberDataType for derived instances, or NULL.
*/ */
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement, NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
const unsigned int minValue, const unsigned int maxValue, const int divisor) const unsigned int minValue, const unsigned int maxValue, const int divisor,
const NumberDataType* baseType)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor), : DataType(id, bitCount, flags|NUM, replacement), m_minValue(minValue), m_maxValue(maxValue), m_divisor(divisor),
m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(NULL) {} m_precision(calcPrecision(divisor)), m_firstBit(0), m_baseType(baseType) {}
/** /**
* Constructs a new instance for less than 8 bits. * Constructs a new instance for less than 8 bits.
@@ -412,11 +417,12 @@ class NumberDataType : public DataType {
* @param replacement the replacement value (no replacement if zero). * @param replacement the replacement value (no replacement if zero).
* @param firstBit the offset to the first bit. * @param firstBit the offset to the first bit.
* @param divisor the divisor (negative for reciprocal). * @param divisor the divisor (negative for reciprocal).
* @param baseType the base @a NumberDataType for derived instances, or NULL.
*/ */
NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement, NumberDataType(const string id, const size_t bitCount, const uint16_t flags, const unsigned int replacement,
const int16_t firstBit, const int divisor) const int16_t firstBit, const int divisor, const NumberDataType* baseType = NULL)
: DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor), : DataType(id, bitCount, flags|NUM, replacement), m_minValue(0), m_maxValue((1 << bitCount)-1), m_divisor(divisor),
m_precision(0), m_firstBit(firstBit), m_baseType(NULL) {} m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
/** /**
* Destructor. * Destructor.
@@ -444,7 +450,7 @@ class NumberDataType : public DataType {
* not necessary. * not necessary.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t derive(int divisor, size_t bitCount, NumberDataType* &derived); virtual result_t derive(int divisor, size_t bitCount, const NumberDataType* &derived) const;
/** /**
* @return the minimum raw value. * @return the minimum raw value.
@@ -472,14 +478,14 @@ class NumberDataType : public DataType {
int16_t getFirstBit() const { return m_firstBit; } int16_t getFirstBit() const { return m_firstBit; }
// @copydoc // @copydoc
result_t readRawValue(SymbolString& input, result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
unsigned int& value) override; unsigned int& value) const override;
// @copydoc // @copydoc
result_t readSymbols(SymbolString& input, result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override; ostringstream& output, OutputFormat outputFormat) const override;
/** /**
* Internal method for writing the numeric raw value to a @a SymbolString. * Internal method for writing the numeric raw value to a @a SymbolString.
@@ -493,12 +499,12 @@ class NumberDataType : public DataType {
*/ */
result_t writeRawValue(unsigned int value, result_t writeRawValue(unsigned int value,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength = NULL); SymbolString& output, size_t* usedLength = NULL) const;
// @copydoc // @copydoc
result_t writeSymbols(istringstream& input, result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length, const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override; SymbolString& output, size_t* usedLength) const override;
private: private:
@@ -518,7 +524,7 @@ class NumberDataType : public DataType {
const int16_t m_firstBit; const int16_t m_firstBit;
/** the base @a NumberDataType for derived instances. */ /** the base @a NumberDataType for derived instances. */
NumberDataType* m_baseType; const NumberDataType* m_baseType;
}; };
@@ -556,13 +562,13 @@ class DataTypeList {
* @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(DataType* dataType); result_t add(const DataType* dataType);
/** /**
* Adds a @a DataType instance for later cleanup. * Adds a @a DataType instance for later cleanup.
* @param dataType the @a DataType instance to add. * @param dataType the @a DataType instance to add.
*/ */
void addCleanup(DataType* dataType) { m_cleanupTypes.push_back(dataType); } void addCleanup(const DataType* dataType) { m_cleanupTypes.push_back(dataType); }
/** /**
* Gets the @a DataType instance with the specified ID. * Gets the @a DataType instance with the specified ID.
@@ -571,30 +577,30 @@ class DataTypeList {
* @return the @a DataType instance, or NULL if not available. * @return the @a DataType instance, or NULL if not available.
* Note: the caller may not free the instance. * Note: the caller may not free the instance.
*/ */
DataType* get(const string id, const size_t length = 0); const DataType* get(const string id, const size_t length = 0) const;
/** /**
* Returns an iterator pointing to the first ID/@a DataType pair. * Returns an iterator pointing to the first ID/@a DataType pair.
* @return an iterator pointing to the first ID/@a DataType pair. * @return an iterator pointing to the first ID/@a DataType pair.
*/ */
map<string, DataType*>::const_iterator begin() const { return m_typesById.begin(); } map<string, const DataType*>::const_iterator begin() const { return m_typesById.begin(); }
/** /**
* Returns an iterator pointing one past the last ID/@a DataType pair. * Returns an iterator pointing one past the last ID/@a DataType pair.
* @return an iterator pointing one past the last ID/@a DataType pair. * @return an iterator pointing one past the last ID/@a DataType pair.
*/ */
map<string, DataType*>::const_iterator end() const { return m_typesById.end(); } map<string, const DataType*>::const_iterator end() const { return m_typesById.end(); }
private: private:
/** the known @a DataType instances by ID only. */ /** the known @a DataType instances by ID only. */
map<string, DataType*> m_typesById; map<string, const DataType*> m_typesById;
/** the known @a DataType instances by ID and length (i.e. "ID:BITS"). /** the known @a DataType instances by ID and length (i.e. "ID:BITS").
* Note: adjustable length types are stored by ID only. */ * Note: adjustable length types are stored by ID only. */
map<string, DataType*> m_typesByIdLength; map<string, const DataType*> m_typesByIdLength;
/** the @a DataType instances to cleanup. */ /** the @a DataType instances to cleanup. */
list<DataType*> m_cleanupTypes; list<const DataType*> m_cleanupTypes;
/** the singleton instance. */ /** the singleton instance. */
static DataTypeList s_instance; static DataTypeList s_instance;
+7 -3
View File
@@ -75,11 +75,14 @@ result_t FileReader::readFromFile(const string filename, string& errorDescriptio
result_t FileReader::readLineFromStream(istream& stream, string& errorDescription, result_t FileReader::readLineFromStream(istream& stream, string& errorDescription,
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose, const string filename, unsigned int& lineNo, vector<string>& row, bool verbose,
size_t* hash, size_t* size) { size_t* hash, size_t* size) {
result_t result;
if (!splitFields(stream, row, lineNo, hash, size)) { if (!splitFields(stream, row, lineNo, hash, size)) {
return RESULT_ERR_EOF; errorDescription = "blank line";
result = RESULT_ERR_EOF;
} else {
errorDescription = "";
result = addFromFile(row, errorDescription, filename, lineNo);
} }
errorDescription = "";
result_t result = addFromFile(row, errorDescription, filename, lineNo);
if (result != RESULT_OK) { if (result != RESULT_OK) {
if (!verbose) { if (!verbose) {
ostringstream error; ostringstream error;
@@ -134,6 +137,7 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
*size += length + 1; // normalized with trailing endl *size += length + 1; // normalized with trailing endl
} }
if (hash) { if (hash) {
// TODO ensure 32 bit machine produces same result
*hash ^= (hashFunction(line) << 1) ^ (length << (7 * (lineNo % 5))); *hash ^= (hashFunction(line) << 1) ^ (length << (7 * (lineNo % 5)));
} }
if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) { if (!quotedText && (length == 0 || line[0] == '#' || (line.length() > 1 && line[0] == '/' && line[1] == '/'))) {
+4 -4
View File
@@ -185,7 +185,7 @@ class MappedFileReader : public FileReader {
* @return true if the minimum parts were extracted, false otherwise. * @return true if the minimum parts were extracted, false otherwise.
*/ */
virtual bool extractDefaultsFromFilename(string filename, map<string, string>& defaults, virtual bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) { symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const {
return false; return false;
} }
@@ -199,7 +199,7 @@ class MappedFileReader : public FileReader {
* @param errorDescription a string in which to store the error description in case of error. * @param errorDescription a string in which to store the error description in case of error.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t getFieldMap(vector<string>& row, string& errorDescription) = 0; virtual result_t getFieldMap(vector<string>& row, string& errorDescription) const = 0;
/** /**
* Add a default row that was read from a file. * Add a default row that was read from a file.
@@ -231,14 +231,14 @@ class MappedFileReader : public FileReader {
/** /**
* @return a reference to all previously extracted default values by type and field name. * @return a reference to all previously extracted default values by type and field name.
*/ */
virtual map<string, map<string, string> >& getDefaults() { map<string, map<string, string> >& getDefaults() {
return m_lastDefaults; return m_lastDefaults;
} }
/** /**
* @return a reference to all previously extracted sub default values by type and field name. * @return a reference to all previously extracted sub default values by type and field name.
*/ */
virtual map<string, vector< map<string, string> > >& getSubDefaults() { map<string, vector< map<string, string> > >& getSubDefaults() {
return m_lastSubDefaults; return m_lastSubDefaults;
} }
+231 -206
View File
@@ -161,20 +161,20 @@ string getMessageFieldName(size_t fieldId, bool withDataFields = true) {
} }
Message::Message(const string circuit, const string level, 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 map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress, const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id, const vector<symbol_t> id,
DataField* data, const bool deleteData, const DataField* data, const bool deleteData,
const size_t pollPriority, const size_t pollPriority,
Condition* condition) Condition* condition)
: m_circuit(circuit), m_level(level), m_name(name), m_isWrite(isWrite), : AttributedItem(name, attributes), m_circuit(circuit), m_level(level), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(comment), m_isPassive(isPassive),
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),
m_pollPriority(pollPriority), m_pollPriority(pollPriority),
m_usedByCondition(false), m_isScanMessage(false), m_condition(condition), m_usedByCondition(false), m_isScanMessage(false), m_condition(condition),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) { m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0),
m_key = createKey(id, isWrite, isPassive, srcAddress, dstAddress); m_key(createKey(id, isWrite, isPassive, srcAddress, dstAddress)) {
if (circuit == "scan") { if (circuit == "scan") {
setScanMessage(); setScanMessage();
m_pollPriority = 0; m_pollPriority = 0;
@@ -183,22 +183,15 @@ Message::Message(const string circuit, const string level, const string name,
Message::Message(const string circuit, const string level, const string name, Message::Message(const string circuit, const string level, const string name,
const symbol_t pb, const symbol_t sb, const symbol_t pb, const symbol_t sb,
const bool broadcast, DataField* data, const bool deleteData) const bool broadcast, const DataField* data, const bool deleteData)
: m_circuit(circuit), m_level(level), m_name(name), m_isWrite(broadcast), : AttributedItem(name), m_circuit(circuit), m_level(level), m_isWrite(broadcast),
m_isPassive(false), m_comment(), m_isPassive(false),
m_srcAddress(SYN), m_dstAddress(broadcast ? BROADCAST : SYN), m_srcAddress(SYN), m_dstAddress(broadcast ? BROADCAST : SYN),
m_data(data), m_deleteData(deleteData), m_id({pb, sb}), m_data(data), m_deleteData(deleteData),
m_pollPriority(0), m_pollPriority(0),
m_usedByCondition(false), m_isScanMessage(true), m_condition(NULL), m_usedByCondition(false), m_isScanMessage(true), m_condition(NULL),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) { m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0),
m_id.push_back(pb); m_key(createKey(pb, sb, broadcast)) {
m_id.push_back(sb);
uint64_t key = 0;
key |= (broadcast ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
key |= (uint64_t)(broadcast ? BROADCAST : SYN) << (8 * 6);
key |= (uint64_t)pb << (8 * 5);
key |= (uint64_t)sb << (8 * 4);
m_key = key;
} }
@@ -214,7 +207,7 @@ Message::Message(const string circuit, const string level, const string name,
* empty and @p replaceStar is @p true. * empty and @p replaceStar is @p true.
* @return the default if available and value is empty, or the value. * @return the default if available and value is empty, or the value.
*/ */
string getDefault(const string value, map<string, string>& defaults, const string fieldName, string getDefault(const string value, const map<string, string>& defaults, const string fieldName,
bool replaceStar = false, bool required = false) { bool replaceStar = false, bool required = false) {
if (defaults.empty()) { if (defaults.empty()) {
return value; return value;
@@ -222,7 +215,8 @@ string getDefault(const string value, map<string, string>& defaults, const strin
if (value.length() == 0 && replaceStar && required) { if (value.length() == 0 && replaceStar && required) {
return value; return value;
} }
string defaultStr = defaults[fieldName]; auto it = defaults.find(fieldName);
const string defaultStr = it == defaults.end() ? "" : it->second;
if (!replaceStar || defaultStr.empty()) { if (!replaceStar || defaultStr.empty()) {
return value.length() > 0 ? value : defaultStr; return value.length() > 0 ? value : defaultStr;
} }
@@ -279,6 +273,15 @@ uint64_t Message::createKey(MasterSymbolString& master, size_t maxIdLength, bool
return key; return key;
} }
uint64_t Message::createKey(const symbol_t pb, const symbol_t sb, const bool broadcast) {
uint64_t key = 0;
key |= (broadcast ? 0x1fLL : 0x1eLL) << (8 * 7); // special values for active
key |= (uint64_t)(broadcast ? BROADCAST : SYN) << (8 * 6);
key |= (uint64_t)pb << (8 * 5);
key |= (uint64_t)sb << (8 * 4);
return key;
}
result_t Message::parseId(string input, vector<symbol_t>& id) { result_t Message::parseId(string input, vector<symbol_t>& id) {
istringstream in(input); istringstream in(input);
while (!in.eof()) { while (!in.eof()) {
@@ -314,8 +317,9 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
bool isWrite = false, isPassive = false; bool isWrite = false, isPassive = false;
string defaultName; string defaultName;
size_t pollPriority = 0; size_t pollPriority = 0;
string typeStr = row["type"]; string typeStr = pluck(row, "type");
if (typeStr.empty()) { if (typeStr.empty()) {
errorDescription = "empty type";
return RESULT_ERR_EOF; return RESULT_ERR_EOF;
} }
if (typeStr.empty()) { // default: active read if (typeStr.empty()) { // default: active read
@@ -341,36 +345,39 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
} }
map<string, string>& defaults = rowDefaults[defaultName]; map<string, string>& defaults = rowDefaults[defaultName];
string circuit = getDefault(row["circuit"], defaults, "circuit", true); // [circuit[#level]] string circuit = getDefault(pluck(row, "circuit"), defaults, "circuit", true); // [circuit[#level]]
string level = getDefault(row["level"], defaults, "level", true); string level = getDefault(pluck(row, "level"), defaults, "level", true);
size_t pos = circuit.find('#'); // TODO remove some day size_t pos = circuit.find('#'); // TODO remove some day
if (pos != string::npos) { if (pos != string::npos) {
level = circuit.substr(pos+1); level = circuit.substr(pos+1);
circuit.resize(pos); circuit.resize(pos);
} }
string name = getDefault(row["name"], defaults, "name", true, true); // name string name = getDefault(pluck(row, "name"), defaults, "name", true, true); // name
if (name.empty()) { if (name.empty()) {
errorDescription = "name in "+MappedFileReader::combineRow(row); errorDescription = "name";
return RESULT_ERR_MISSING_ARG; // empty name return RESULT_ERR_MISSING_ARG; // empty name
} }
string comment = getDefault(row["comment"], defaults, "comment", true); // [comment] string comment = getDefault(pluck(row, "comment"), defaults, "comment", true); // [comment]
string str = getDefault(row["qq"], defaults, "qq"); // [QQ[;QQ]*] if (!comment.empty()) {
row["comment"] = comment;
}
string str = getDefault(pluck(row, "qq"), defaults, "qq"); // [QQ[;QQ]*]
symbol_t srcAddress; symbol_t srcAddress;
if (str.empty()) { if (str.empty()) {
srcAddress = SYN; // no specific source srcAddress = SYN; // no specific source
} else { } else {
srcAddress = (symbol_t)parseInt(str.c_str(), 16, 0, 0xff, result); srcAddress = (symbol_t)parseInt(str.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) { if (result != RESULT_OK) {
errorDescription = "qq "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "qq "+str;
return result; return result;
} }
if (!isMaster(srcAddress)) { if (!isMaster(srcAddress)) {
errorDescription = "qq "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "qq "+str;
return RESULT_ERR_INVALID_ADDR; return RESULT_ERR_INVALID_ADDR;
} }
} }
str = getDefault(row["zz"], defaults, "zz"); // [ZZ] str = getDefault(pluck(row, "zz"), defaults, "zz"); // [ZZ]
vector<symbol_t> dstAddresses; vector<symbol_t> dstAddresses;
bool isBroadcastOrMasterDestination = false; bool isBroadcastOrMasterDestination = false;
if (str.empty()) { if (str.empty()) {
@@ -383,11 +390,11 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
FileReader::trim(token); FileReader::trim(token);
symbol_t dstAddress = (symbol_t)parseInt(token.c_str(), 16, 0, 0xff, result); symbol_t dstAddress = (symbol_t)parseInt(token.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) { if (result != RESULT_OK) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row); errorDescription = "zz "+token;
return result; return result;
} }
if (!isValidAddress(dstAddress)) { if (!isValidAddress(dstAddress)) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row); errorDescription = "zz "+token;
return RESULT_ERR_INVALID_ADDR; return RESULT_ERR_INVALID_ADDR;
} }
bool broadcastOrMaster = (dstAddress == BROADCAST) || isMaster(dstAddress); bool broadcastOrMaster = (dstAddress == BROADCAST) || isMaster(dstAddress);
@@ -395,7 +402,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
isBroadcastOrMasterDestination = broadcastOrMaster; isBroadcastOrMasterDestination = broadcastOrMaster;
first = false; first = false;
} else if (isBroadcastOrMasterDestination != broadcastOrMaster) { } else if (isBroadcastOrMasterDestination != broadcastOrMaster) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row); errorDescription = "zz "+token;
return RESULT_ERR_INVALID_ADDR; return RESULT_ERR_INVALID_ADDR;
} }
dstAddresses.push_back(dstAddress); dstAddresses.push_back(dstAddress);
@@ -403,21 +410,21 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
} }
vector<symbol_t> id; vector<symbol_t> id;
str = row["pbsb"]; // [PBSB] str = pluck(row, "pbsb"); // [PBSB]
bool useDefaults = str.empty(); bool useDefaults = str.empty();
if (useDefaults) { if (useDefaults) {
str = getDefault(str, defaults, "pbsb"); str = getDefault(str, defaults, "pbsb");
} }
result = parseId(str, id); result = parseId(str, id);
if (result != RESULT_OK) { if (result != RESULT_OK) {
errorDescription = "pbsb "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "pbsb "+str;
return result; return result;
} }
if (id.size() != 2) { if (id.size() != 2) {
errorDescription = "pbsb "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "pbsb "+str;
return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB return RESULT_ERR_INVALID_ARG; // missing/to short/to long PBSB
} }
str = row["id"]; // [ID] (optional master data) str = pluck(row, "id"); // [ID] (optional master data)
string defaultIdPrefix; string defaultIdPrefix;
if (useDefaults) { if (useDefaults) {
defaultIdPrefix = getDefault("", defaults, "id"); defaultIdPrefix = getDefault("", defaults, "id");
@@ -437,7 +444,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
if (lastChainLengthSpecified) { if (lastChainLengthSpecified) {
chainLength = parseInt(str.substr(lengthPos+1).c_str(), 10, 0, MAX_POS, result); chainLength = parseInt(str.substr(lengthPos+1).c_str(), 10, 0, MAX_POS, result);
if (result != RESULT_OK) { if (result != RESULT_OK) {
errorDescription = "id "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "id "+str;
return result; return result;
} }
str.resize(lengthPos); str.resize(lengthPos);
@@ -445,11 +452,11 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
vector<symbol_t> chainId = id; vector<symbol_t> chainId = id;
result = parseId(str, chainId); result = parseId(str, chainId);
if (result != RESULT_OK) { if (result != RESULT_OK) {
errorDescription = "id "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "id "+str;
return result; return result;
} }
if (!chainIds.empty() && chainId.size() != chainIds.front().size()) { if (!chainIds.empty() && chainId.size() != chainIds.front().size()) {
errorDescription = "id length "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "id length "+str;
return RESULT_ERR_INVALID_LIST; return RESULT_ERR_INVALID_LIST;
} }
chainIds.push_back(chainId); chainIds.push_back(chainId);
@@ -467,7 +474,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
} }
} }
if (maxLength+chainLength > 255) { if (maxLength+chainLength > 255) {
errorDescription = "id length "+str+" in "+MappedFileReader::combineRow(row); errorDescription = "id length "+str;
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
maxLength += chainLength; maxLength += chainLength;
@@ -476,7 +483,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
id = chainIds.front(); id = chainIds.front();
if (chainIds.size() > 1) { if (chainIds.size() > 1) {
if (isPassive) { if (isPassive) {
errorDescription = "id (passive) in "+MappedFileReader::combineRow(row); errorDescription = "id (passive)";
return RESULT_ERR_INVALID_LIST; return RESULT_ERR_INVALID_LIST;
} }
if (id.size() > chainPrefixLength) { if (id.size() > chainPrefixLength) {
@@ -493,10 +500,10 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
if (!subDefaults.empty()) { if (!subDefaults.empty()) {
subRows.insert(subRows.begin(), subDefaults.begin(), subDefaults.end()); subRows.insert(subRows.begin(), subDefaults.begin(), subDefaults.end());
} }
DataField* data = NULL; const DataField* data = NULL;
if (subRows.empty()) { if (subRows.empty()) {
vector<SingleDataField*> fields; vector<const SingleDataField*> fields;
data = new DataFieldSet("", "", fields); data = new DataFieldSet("", fields);
} else { } else {
result = DataField::create(subRows, errorDescription, templates, data, isWrite, false, result = DataField::create(subRows, errorDescription, templates, data, isWrite, false,
isBroadcastOrMasterDestination, maxLength); isBroadcastOrMasterDestination, maxLength);
@@ -508,7 +515,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
|| data->getLength(pt_slaveData, maxLength) > maxLength) { || data->getLength(pt_slaveData, maxLength) > maxLength) {
// max NN exceeded // max NN exceeded
delete data; delete data;
errorDescription = "data length in "+MappedFileReader::combineRow(row); errorDescription = "data length";
return RESULT_ERR_INVALID_POS; return RESULT_ERR_INVALID_POS;
} }
unsigned int index = 0; unsigned int index = 0;
@@ -523,10 +530,10 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
} }
Message* message; Message* message;
if (chainIds.size() > 1) { if (chainIds.size() > 1) {
message = new ChainedMessage(useCircuit, level, name, isWrite, comment, srcAddress, dstAddress, id, chainIds, message = new ChainedMessage(useCircuit, level, name, isWrite, row, srcAddress, dstAddress, id, chainIds,
chainLengths, data, index == 0, pollPriority, condition); chainLengths, data, index == 0, pollPriority, condition);
} else { } else {
message = new Message(useCircuit, level, name, isWrite, isPassive, comment, srcAddress, dstAddress, id, data, message = new Message(useCircuit, level, name, isWrite, isPassive, row, srcAddress, dstAddress, id, data,
index == 0, pollPriority, condition); index == 0, pollPriority, condition);
} }
messages.push_back(message); messages.push_back(message);
@@ -561,9 +568,9 @@ bool Message::extractFieldIds(string str, vector<size_t>& fields, bool checkAbbr
return !fields.empty(); return !fields.empty();
} }
Message* Message::derive(const symbol_t dstAddress, const symbol_t srcAddress, const string circuit) { Message* Message::derive(const symbol_t dstAddress, const symbol_t srcAddress, const string circuit) const {
Message* result = new Message(circuit.length() == 0 ? m_circuit : circuit, m_level, 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_attributes,
srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress, srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_data, false, m_id, m_data, false,
m_pollPriority, m_condition); m_pollPriority, m_condition);
@@ -573,7 +580,7 @@ Message* Message::derive(const symbol_t dstAddress, const symbol_t srcAddress, c
return result; return result;
} }
Message* Message::derive(const symbol_t dstAddress, const bool extendCircuit) { Message* Message::derive(const symbol_t dstAddress, const bool extendCircuit) const {
if (extendCircuit) { if (extendCircuit) {
ostringstream out; ostringstream out;
out << m_circuit << '.' << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress); out << m_circuit << '.' << hex << setw(2) << setfill('0') << static_cast<unsigned>(dstAddress);
@@ -604,7 +611,8 @@ bool Message::checkLevel(const string level, const string checkLevels) {
} }
return false; return false;
} }
bool Message::checkIdPrefix(vector<symbol_t>& id) {
bool Message::checkIdPrefix(const vector<symbol_t>& id) const {
if (id.size() > m_id.size()) { if (id.size() > m_id.size()) {
return false; return false;
} }
@@ -616,7 +624,7 @@ bool Message::checkIdPrefix(vector<symbol_t>& id) {
return true; return true;
} }
bool Message::checkId(MasterSymbolString& master, size_t* index) { bool Message::checkId(const MasterSymbolString& master, size_t* index) const {
size_t idLen = getIdLength(); size_t idLen = getIdLength();
if (master.getDataSize() < idLen) { if (master.getDataSize() < idLen) {
return false; return false;
@@ -632,7 +640,7 @@ bool Message::checkId(MasterSymbolString& master, size_t* index) {
return true; return true;
} }
bool Message::checkId(Message& other) { bool Message::checkId(Message& other) const {
size_t idLen = getIdLength(); size_t idLen = getIdLength();
if (idLen != other.getIdLength() || getCount() > 1) { // only equal for non-chained messages if (idLen != other.getIdLength() || getCount() > 1) { // only equal for non-chained messages
return false; return false;
@@ -640,7 +648,7 @@ bool Message::checkId(Message& other) {
return other.checkIdPrefix(m_id); return other.checkIdPrefix(m_id);
} }
uint64_t Message::getDerivedKey(const symbol_t dstAddress) { uint64_t Message::getDerivedKey(const symbol_t dstAddress) const {
return (m_key & ~(0xffLL << (8*6))) | (uint64_t)dstAddress << (8*6); return (m_key & ~(0xffLL << (8*6))) | (uint64_t)dstAddress << (8*6);
} }
@@ -670,7 +678,7 @@ bool Message::isAvailable() {
return (m_condition == NULL) || m_condition->isTrue(); return (m_condition == NULL) || m_condition->isTrue();
} }
bool Message::hasField(const char* fieldName, bool numeric) { bool Message::hasField(const char* fieldName, bool numeric) const {
return m_data->hasField(fieldName, numeric); return m_data->hasField(fieldName, numeric);
} }
@@ -749,8 +757,8 @@ result_t Message::storeLastData(MasterSymbolString& master, SlaveSymbolString& s
} }
result_t Message::storeLastData(MasterSymbolString& data, size_t index) { result_t Message::storeLastData(MasterSymbolString& data, size_t index) {
if (data.size() > 0 if (data.size() > 0 && (m_isWrite || this->m_dstAddress == BROADCAST || isMaster(this->m_dstAddress)
&& (m_isWrite || this->m_dstAddress == BROADCAST || isMaster(this->m_dstAddress))) { || data.getDataSize() + 2 > m_id.size())) {
time(&m_lastUpdateTime); time(&m_lastUpdateTime);
} }
switch (data.compareTo(m_lastMasterData)) { switch (data.compareTo(m_lastMasterData)) {
@@ -761,6 +769,7 @@ result_t Message::storeLastData(MasterSymbolString& data, size_t index) {
case 2: // only master address is different case 2: // only master address is different
m_lastMasterData = data; m_lastMasterData = data;
break; break;
// else: identical
} }
return RESULT_OK; return RESULT_OK;
} }
@@ -772,12 +781,13 @@ result_t Message::storeLastData(SlaveSymbolString& data, size_t index) {
if (data != m_lastSlaveData) { if (data != m_lastSlaveData) {
m_lastChangeTime = m_lastUpdateTime; m_lastChangeTime = m_lastUpdateTime;
m_lastSlaveData = data; m_lastSlaveData = data;
const SlaveSymbolString& chk = getLastSlaveData();
} }
return RESULT_OK; return RESULT_OK;
} }
result_t Message::decodeLastMasterData(ostringstream& output, OutputFormat outputFormat, result_t Message::decodeLastMasterData(ostringstream& output, OutputFormat outputFormat,
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) { bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) const {
size_t offset = m_id.size() - 2; size_t offset = m_id.size() - 2;
result_t result = m_data->read(m_lastMasterData, offset, result_t result = m_data->read(m_lastMasterData, offset,
output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex); output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
@@ -791,7 +801,7 @@ result_t Message::decodeLastMasterData(ostringstream& output, OutputFormat outpu
} }
result_t Message::decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat, result_t Message::decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat,
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) { bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) const {
result_t result = m_data->read(m_lastSlaveData, 0, result_t result = m_data->read(m_lastSlaveData, 0,
output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex); output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
if (result < RESULT_OK) { if (result < RESULT_OK) {
@@ -804,7 +814,7 @@ result_t Message::decodeLastSlaveData(ostringstream& output, OutputFormat output
} }
result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat, result_t Message::decodeLastData(ostringstream& output, OutputFormat outputFormat,
bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) { bool leadingSeparator, const char* fieldName, ssize_t fieldIndex) const {
size_t startPos = output.str().length(); size_t startPos = output.str().length();
result_t result = m_data->read(m_lastMasterData, getIdLength(), output, outputFormat, -1, result_t result = m_data->read(m_lastMasterData, getIdLength(), output, outputFormat, -1,
leadingSeparator, fieldName, fieldIndex); leadingSeparator, fieldName, fieldIndex);
@@ -825,7 +835,7 @@ result_t Message::decodeLastData(ostringstream& output, OutputFormat outputForma
return result; return result;
} }
result_t Message::decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex) { result_t Message::decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex) const {
result_t result = m_data->read(m_lastMasterData, getIdLength(), output, fieldName, fieldIndex); result_t result = m_data->read(m_lastMasterData, getIdLength(), output, fieldName, fieldIndex);
if (result < RESULT_OK) { if (result < RESULT_OK) {
return result; return result;
@@ -842,7 +852,7 @@ result_t Message::decodeLastDataNumField(unsigned int& output, const char* field
return result; return result;
} }
bool Message::isLessPollWeight(const Message* other) { bool Message::isLessPollWeight(const Message* other) const {
size_t tprio = m_pollPriority; size_t tprio = m_pollPriority;
size_t oprio = other->m_pollPriority; size_t oprio = other->m_pollPriority;
size_t tw = tprio * m_pollCount; size_t tw = tprio * m_pollCount;
@@ -909,7 +919,7 @@ void Message::dumpHeader(ostream& output, vector<size_t>* fieldIds) {
} }
} }
void Message::dump(ostream& output, vector<size_t>* fieldIds, bool withConditions) { void Message::dump(ostream& output, vector<size_t>* fieldIds, bool withConditions) const {
bool first = true; bool first = true;
if (fieldIds == NULL) { if (fieldIds == NULL) {
for (size_t fieldId = MESSAGEFIELD_RANGE_MIN; fieldId <= MESSAGEFIELD_RANGE_MAX; fieldId++) { for (size_t fieldId = MESSAGEFIELD_RANGE_MIN; fieldId <= MESSAGEFIELD_RANGE_MAX; fieldId++) {
@@ -935,7 +945,7 @@ void Message::dump(ostream& output, vector<size_t>* fieldIds, bool withCondition
} }
} }
void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) { void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) const {
switch (fieldId) { switch (fieldId) {
case MESSAGEFIELD_TYPE: case MESSAGEFIELD_TYPE:
if (withConditions && m_condition != NULL) { if (withConditions && m_condition != NULL) {
@@ -956,16 +966,16 @@ void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) {
} }
break; break;
case MESSAGEFIELD_CIRCUIT: case MESSAGEFIELD_CIRCUIT:
DataField::dumpString(output, m_circuit, false); dumpString(output, m_circuit, false);
break; break;
case MESSAGEFIELD_LEVEL: case MESSAGEFIELD_LEVEL:
DataField::dumpString(output, m_level, false); dumpString(output, m_level, false);
break; break;
case MESSAGEFIELD_NAME: case MESSAGEFIELD_NAME:
DataField::dumpString(output, m_name, false); dumpString(output, m_name, false);
break; break;
case MESSAGEFIELD_COMMENT: case MESSAGEFIELD_COMMENT:
DataField::dumpString(output, m_comment, false); dumpAttribute(output, "comment", false);
break; break;
case MESSAGEFIELD_QQ: case MESSAGEFIELD_QQ:
if (m_srcAddress != SYN) { if (m_srcAddress != SYN) {
@@ -997,14 +1007,14 @@ void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) {
ChainedMessage::ChainedMessage(const string circuit, const string level, const string name, ChainedMessage::ChainedMessage(const string circuit, const string level, const string name,
const bool isWrite, const string comment, const bool isWrite, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress, const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id, const vector<symbol_t> id,
vector< vector<symbol_t> > ids, vector<size_t> lengths, vector< vector<symbol_t> > ids, vector<size_t> lengths,
DataField* data, const bool deleteData, const DataField* data, const bool deleteData,
const size_t pollPriority, const size_t pollPriority,
Condition* condition) Condition* condition)
: Message(circuit, level, name, isWrite, false, comment, : Message(circuit, level, name, isWrite, false, attributes,
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),
@@ -1033,9 +1043,9 @@ ChainedMessage::~ChainedMessage() {
free(m_lastSlaveUpdateTimes); free(m_lastSlaveUpdateTimes);
} }
Message* ChainedMessage::derive(const symbol_t dstAddress, const symbol_t srcAddress, const string circuit) { Message* ChainedMessage::derive(const symbol_t dstAddress, const symbol_t srcAddress, const string circuit) const {
ChainedMessage* result = new ChainedMessage(circuit.length() == 0 ? m_circuit : circuit, m_level, m_name, ChainedMessage* result = new ChainedMessage(circuit.length() == 0 ? m_circuit : circuit, m_level, m_name,
m_isWrite, m_comment, m_isWrite, m_attributes,
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,
m_pollPriority, m_condition); m_pollPriority, m_condition);
@@ -1045,7 +1055,7 @@ Message* ChainedMessage::derive(const symbol_t dstAddress, const symbol_t srcAdd
return result; return result;
} }
bool ChainedMessage::checkId(MasterSymbolString& master, size_t* index) { bool ChainedMessage::checkId(const MasterSymbolString& master, size_t* index) const {
size_t idLen = getIdLength(); size_t idLen = getIdLength();
if (master.getDataSize() < idLen) { if (master.getDataSize() < idLen) {
return false; return false;
@@ -1076,7 +1086,7 @@ bool ChainedMessage::checkId(MasterSymbolString& master, size_t* index) {
return false; return false;
} }
bool ChainedMessage::checkId(Message& other) { bool ChainedMessage::checkId(Message& other) const {
size_t idLen = getIdLength(); size_t idLen = getIdLength();
if (idLen != other.getIdLength() || other.getCount() == 1) { // only equal for chained messages if (idLen != other.getIdLength() || other.getCount() == 1) { // only equal for chained messages
return false; return false;
@@ -1242,7 +1252,7 @@ result_t ChainedMessage::combineLastParts() {
return result; return result;
} }
void ChainedMessage::dumpField(ostream& output, size_t fieldId, bool withConditions) { void ChainedMessage::dumpField(ostream& output, size_t fieldId, bool withConditions) const {
if (fieldId != MESSAGEFIELD_ID) { if (fieldId != MESSAGEFIELD_ID) {
Message::dumpField(output, fieldId, withConditions); Message::dumpField(output, fieldId, withConditions);
return; return;
@@ -1270,10 +1280,9 @@ void ChainedMessage::dumpField(ostream& output, size_t fieldId, bool withConditi
* @param onlyAvailable true to include only available messages (default true), false to also include messages that * @param onlyAvailable true to include only available messages (default true), false to also include messages that
* are currently not available (e.g. due to unresolved or false conditions). * are currently not available (e.g. due to unresolved or false conditions).
*/ */
Message* getFirstAvailable(vector<Message*> &messages, MasterSymbolString* sameIdExtAs, Message* getFirstAvailable(const vector<Message*> &messages, const MasterSymbolString* sameIdExtAs,
const bool onlyAvailable = true) { const bool onlyAvailable = true) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++) { for (auto message : messages) {
Message* message = *msgIt;
if (sameIdExtAs && !message->checkId(*sameIdExtAs)) { if (sameIdExtAs && !message->checkId(*sameIdExtAs)) {
continue; continue;
} }
@@ -1291,10 +1300,9 @@ Message* getFirstAvailable(vector<Message*> &messages, MasterSymbolString* sameI
* @param onlyAvailable true to include only available messages (default true), false to also include messages that * @param onlyAvailable true to include only available messages (default true), false to also include messages that
* are currently not available (e.g. due to unresolved or false conditions). * are currently not available (e.g. due to unresolved or false conditions).
*/ */
Message* getFirstAvailable(vector<Message*> &messages, Message* sameIdExtAs = NULL, Message* getFirstAvailable(const vector<Message*> &messages, Message* sameIdExtAs = NULL,
const bool onlyAvailable = true) { const bool onlyAvailable = true) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++) { for (auto message : messages) {
Message* message = *msgIt;
if (sameIdExtAs && !message->checkId(*sameIdExtAs)) { if (sameIdExtAs && !message->checkId(*sameIdExtAs)) {
continue; continue;
} }
@@ -1381,7 +1389,7 @@ result_t splitValues(string valueList, vector<unsigned int>& valueRanges) {
result_t Condition::create(const string condName, map<string, string> row, map<string, string> rowDefaults, result_t Condition::create(const string condName, map<string, string> row, map<string, string> rowDefaults,
SimpleCondition*& returnValue) { SimpleCondition*& returnValue) {
// name,circuit,messagename,[comment],[fieldname],[ZZ],values // type=name,circuit,name=messagename,[comment],qq=[fieldname],[ZZ],pbsb=values
string circuit = row["circuit"]; // circuit[#level] string circuit = row["circuit"]; // circuit[#level]
string level; string level;
size_t pos = circuit.find('#'); size_t pos = circuit.find('#');
@@ -1414,7 +1422,10 @@ result_t Condition::create(const string condName, map<string, string> row, map<s
circuit = rowDefaults["circuit"]; circuit = rowDefaults["circuit"];
} }
string valueList = row["pbsb"]; string valueList = row["pbsb"];
if (valueList.length() == 0) { if (valueList.empty()) {
valueList = row["id"];
}
if (valueList.empty()) {
returnValue = new SimpleCondition(condName, condName, circuit, level, name, dstAddress, field); returnValue = new SimpleCondition(condName, condName, circuit, level, name, dstAddress, field);
return RESULT_OK; return RESULT_OK;
} }
@@ -1438,7 +1449,7 @@ result_t Condition::create(const string condName, map<string, string> row, map<s
return RESULT_OK; return RESULT_OK;
} }
SimpleCondition* SimpleCondition::derive(string valueList) { SimpleCondition* SimpleCondition::derive(string valueList) const {
if (valueList.empty()) { if (valueList.empty()) {
return NULL; return NULL;
} }
@@ -1468,7 +1479,7 @@ SimpleCondition* SimpleCondition::derive(string valueList) {
return new SimpleNumericCondition(name, m_refName, m_circuit, m_level, 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) const {
if (matched) { if (matched) {
if (!m_isTrue) { if (!m_isTrue) {
return; return;
@@ -1518,7 +1529,7 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
} }
// clone the message with dedicated dstAddress if necessary // clone the message with dedicated dstAddress if necessary
uint64_t key = message->getDerivedKey(m_dstAddress); uint64_t key = message->getDerivedKey(m_dstAddress);
vector<Message*>* derived = messages->getByKey(key); const vector<Message*>* derived = messages->getByKey(key);
if (derived == NULL) { if (derived == NULL) {
message = message->derive(m_dstAddress, true); message = message->derive(m_dstAddress, true);
messages->add(message); messages->add(message);
@@ -1600,17 +1611,15 @@ bool SimpleStringCondition::checkValue(Message* message, string field) {
} }
void CombinedCondition::dump(ostream& output, bool matched) { void CombinedCondition::dump(ostream& output, bool matched) const {
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) { for (auto condition : m_conditions) {
Condition* condition = *it;
condition->dump(output, matched); condition->dump(output, matched);
} }
} }
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage, result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
void (*readMessageFunc)(Message* message)) { void (*readMessageFunc)(Message* message)) {
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) { for (auto condition : m_conditions) {
Condition* condition = *it;
ostringstream dummy; ostringstream dummy;
result_t ret = condition->resolve(messages, dummy, readMessageFunc); result_t ret = condition->resolve(messages, dummy, readMessageFunc);
if (ret != RESULT_OK) { if (ret != RESULT_OK) {
@@ -1662,23 +1671,28 @@ result_t Instruction::create(const string& contextPath, const string type,
return RESULT_ERR_INVALID_ARG; return RESULT_ERR_INVALID_ARG;
} }
string Instruction::getDestination() { string Instruction::getDestination() const {
// ZZ.circuit[.suffix] // ZZ.circuit[.suffix]
string ret; string ret;
if (!m_defaults["zz"].empty()) { auto it = m_defaults.find("zz");
ret = m_defaults["zz"]; if (it != m_defaults.end() && !it->second.empty()) {
ret = it->second;
} }
if (!m_defaults["circuit"].empty() || !m_defaults["suffix"].empty()) { it = m_defaults.find("circuit");
string circuit = it == m_defaults.end() ? "" : it->second;
it = m_defaults.find("suffix");
string suffix = it == m_defaults.end() ? "" : it->second;
if (!circuit.empty() || !suffix.empty()) {
if (!ret.empty()) { if (!ret.empty()) {
ret += "."; ret += ".";
} }
if (m_defaults["circuit"].empty()) { if (circuit.empty()) {
ret += "*"; ret += "*";
} else { } else {
ret += m_defaults["circuit"]; ret += circuit;
} }
if (!m_defaults["suffix"].empty()) { if (!suffix.empty()) {
ret += m_defaults["suffix"]; ret += suffix;
} }
} }
return ret; return ret;
@@ -1725,6 +1739,8 @@ result_t LoadInstruction::execute(MessageMap* messages, ostringstream& log, Cond
} }
vector<string> MessageMap::s_noFiles;
result_t MessageMap::add(Message* message, bool storeByName) { result_t MessageMap::add(Message* message, bool storeByName) {
uint64_t key = message->getKey(); uint64_t key = message->getKey();
bool conditional = message->isConditional(); bool conditional = message->isConditional();
@@ -1763,7 +1779,6 @@ result_t MessageMap::add(Message* message, bool storeByName) {
} }
} }
m_messagesByName[nameKey].push_back(message); m_messagesByName[nameKey].push_back(message);
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit 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()) {
@@ -1800,7 +1815,7 @@ result_t MessageMap::add(Message* message, bool storeByName) {
return RESULT_OK; return RESULT_OK;
} }
result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription) { result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription) const {
// type (r[1-9];w;u),circuit,name,[comment],[QQ],ZZ,PBSB,[ID],field1,part (m/s),datatypes/templates,divider/values, // type (r[1-9];w;u),circuit,name,[comment],[QQ],ZZ,PBSB,[ID],field1,part (m/s),datatypes/templates,divider/values,
// unit,comment // unit,comment
// minimum: type,name,PBSB,field,datatype // minimum: type,name,PBSB,field,datatype
@@ -1826,55 +1841,56 @@ result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription)
bool inDataFields = false; bool inDataFields = false;
map<string, string> seen; map<string, string> seen;
for (auto &name : row) { for (auto &name : row) {
tolower(name); string useName = name;
size_t fieldId; tolower(useName);
if (inDataFields) { if (inDataFields) {
fieldId = getDataFieldId(name); size_t fieldId = getDataFieldId(useName);
if (fieldId == UINT_MAX) { if (fieldId != UINT_MAX) {
errorDescription = "unknown field " + name; useName = getDataFieldName(fieldId);
return RESULT_ERR_INVALID_ARG; if (seen.find(useName) != seen.end()) {
} if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
if (seen.find(name) != seen.end()) { errorDescription = "missing field name/type as of already seen "+useName;
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) { return RESULT_ERR_EOF; // require at least name and type
return RESULT_ERR_EOF; // require at least name and type }
seen.clear();
} }
seen.clear();
name = "*" + getDataFieldName(fieldId); // data field repetition
} else {
name = getDataFieldName(fieldId);
} }
} else { } else {
fieldId = getMessageFieldId(name); size_t fieldId = getMessageFieldId(useName);
if (fieldId == UINT_MAX) { if (fieldId != UINT_MAX && (fieldId != MESSAGEFIELD_NAME || seen.find("name") == seen.end())) {
fieldId = getDataFieldId(name); useName = getMessageFieldName(fieldId);
if (fieldId == UINT_MAX) {
errorDescription = "unknown field " + name;
return RESULT_ERR_INVALID_ARG;
}
if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
return RESULT_ERR_EOF; // require at least type, name, and pbsb
}
inDataFields = true;
seen.clear();
name = "*" + getDataFieldName(fieldId);
} else { } else {
if (seen.find(name) != seen.end()) { fieldId = getDataFieldId(useName);
errorDescription = "duplicate field " + name; if (fieldId != UINT_MAX) {
return RESULT_ERR_INVALID_ARG; useName = getDataFieldName(fieldId);
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
}
inDataFields = true;
seen.clear();
} }
name = getMessageFieldName(fieldId); }
if (!inDataFields && seen.find(useName) != seen.end()) {
errorDescription = "duplicate message " + useName;
return RESULT_ERR_INVALID_ARG;
} }
} }
seen[name] = name; if (seen.empty() && inDataFields) {
name = "*" + useName; // data field repetition
} else {
name = useName;
}
seen[useName] = useName;
} }
if (inDataFields) { if (inDataFields) {
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) { if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
errorDescription = "missing field name/type";
return RESULT_ERR_EOF; // require at least name and type return RESULT_ERR_EOF; // require at least name and type
} }
} else { } else if (seen.find("type") == seen.end() || seen.find("name") == seen.end() || seen.find("pbsb") == seen.end()) {
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 return RESULT_ERR_EOF; // require at least type, name, and pbsb
}
} }
return RESULT_OK; return RESULT_OK;
} }
@@ -1884,9 +1900,13 @@ result_t MessageMap::addDefaultFromFile(map<string, string>& row, vector< map<st
// check for condition in defaults // check for condition in defaults
string type = row["type"]; string type = row["type"];
row.erase("type"); row.erase("type");
auto mainDefaults = getDefaults().find("");
map<string, string> defaults;
if (mainDefaults != getDefaults().end()) {
defaults = mainDefaults->second;
}
if (!type.empty() && type[0] == '[' && type[type.length()-1] == ']') { if (!type.empty() && type[0] == '[' && type[type.length()-1] == ']') {
// condition // condition
map<string, string> defaults = getDefaults()[""];
type = type.substr(1, type.length()-2); type = type.substr(1, type.length()-2);
if (type.find('[') != string::npos || type.find(']') != string::npos) { if (type.find('[') != string::npos || type.find(']') != string::npos) {
errorDescription = "invalid condition name "+type; errorDescription = "invalid condition name "+type;
@@ -1907,41 +1927,40 @@ result_t MessageMap::addDefaultFromFile(map<string, string>& row, vector< map<st
m_conditions[key] = condition; m_conditions[key] = condition;
return RESULT_OK; return RESULT_OK;
} }
if (!type.empty()) { if (type.empty()) {
map<string, string> defaults = getDefaults()[""]; errorDescription = "invalid default definition";
string defaultCircuit = defaults["circuit"]; return RESULT_ERR_INVALID_ARG;
string defaultSuffix = defaults["suffix"]; }
defaults.erase("suffix"); string defaultCircuit = defaults["circuit"];
for (auto entry : row) { string defaultSuffix = defaults["suffix"];
string value = entry.second; defaults.erase("suffix");
if (entry.first == "circuit" && !defaultCircuit.empty()) { // TODO remove some day for (auto entry : row) {
if (value.empty()) { string value = entry.second;
value = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]" if (entry.first == "circuit" && !defaultCircuit.empty()) { // TODO remove some day
} else if (value[0] == '#') { if (value.empty()) {
// move access level behind default circuit and suffix: "circuit[.suffix]#level" value = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
value = defaultCircuit+defaultSuffix+value; } else if (value[0] == '#') {
} else if (!defaultSuffix.empty() && value.find_last_of('.') == string::npos) { // move access level behind default circuit and suffix: "circuit[.suffix]#level"
// circuit suffix not yet present value = defaultCircuit+defaultSuffix+value;
size_t pos = value.find_first_of('#'); } else if (!defaultSuffix.empty() && value.find_last_of('.') == string::npos) {
if (pos == string::npos) { // circuit suffix not yet present
value += defaultSuffix; // append default suffix: "circuit.suffix" size_t pos = value.find_first_of('#');
} else { if (pos == string::npos) {
// insert default suffix: "circuit.suffix#level" value += defaultSuffix; // append default suffix: "circuit.suffix"
value = value.substr(0, pos)+defaultSuffix+value.substr(pos); } else {
} // insert default suffix: "circuit.suffix#level"
value = value.substr(0, pos)+defaultSuffix+value.substr(pos);
} }
} }
if (!value.empty() || defaults[entry.first].empty()) {
defaults[entry.first] = value;
}
} }
getDefaults()[type] = defaults; if (!value.empty() || defaults[entry.first].empty()) {
vector< map<string, string> > subDefaults = subRows; // ensure to have a copy defaults[entry.first] = value;
getSubDefaults()[type] = subDefaults; }
return RESULT_OK;
} }
errorDescription = "invalid default definition"; getDefaults()[type] = defaults;
return RESULT_ERR_INVALID_ARG; vector< map<string, string> > subDefaults = subRows; // ensure to have a copy
getSubDefaults()[type] = subDefaults;
return RESULT_OK;
} }
result_t MessageMap::readConditions(string& types, const string filename, string& errorDescription, result_t MessageMap::readConditions(string& types, const string filename, string& errorDescription,
@@ -1950,7 +1969,7 @@ result_t MessageMap::readConditions(string& types, const string filename, string
if (types.length() > 0 && types[0] == '[' && (pos=types.find_last_of(']')) != string::npos) { if (types.length() > 0 && types[0] == '[' && (pos=types.find_last_of(']')) != string::npos) {
// check if combined or simple condition is already known // check if combined or simple condition is already known
const string combinedkey = filename+":"+types.substr(1, pos-1); const string combinedkey = filename+":"+types.substr(1, pos-1);
map<string, Condition*>::iterator it = m_conditions.find(combinedkey); auto it = m_conditions.find(combinedkey);
if (it != m_conditions.end()) { if (it != m_conditions.end()) {
condition = it->second; condition = it->second;
types = types.substr(pos+1); types = types.substr(pos+1);
@@ -2005,7 +2024,7 @@ result_t MessageMap::readConditions(string& types, const string filename, string
} }
bool MessageMap::extractDefaultsFromFilename(string filename, map<string, string>& defaults, bool MessageMap::extractDefaultsFromFilename(string filename, map<string, string>& defaults,
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) { symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const {
string ident, circuit, suffix; string ident, circuit, suffix;
unsigned int sw = UINT_MAX, hw = UINT_MAX; unsigned int sw = UINT_MAX, hw = UINT_MAX;
string remain = filename; string remain = filename;
@@ -2180,7 +2199,7 @@ Message* MessageMap::getScanMessage(const symbol_t dstAddress) {
return NULL; return NULL;
} }
uint64_t key = m_scanMessage->getDerivedKey(dstAddress); uint64_t key = m_scanMessage->getDerivedKey(dstAddress);
vector<Message*>* msgs = getByKey(key); const vector<Message*>* msgs = getByKey(key);
if (msgs != NULL) { if (msgs != NULL) {
return msgs->front(); return msgs->front();
} }
@@ -2220,12 +2239,11 @@ result_t MessageMap::resolveCondition(Condition* condition, string& errorDescrip
result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message)) { result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageFunc)(Message* message)) {
result_t overallResult = RESULT_OK; result_t overallResult = RESULT_OK;
vector<string> remove; vector<string> remove;
for (map<string, vector<Instruction*> >::iterator it = m_instructions.begin(); it != m_instructions.end(); it++) { for (auto& it : m_instructions) {
vector<Instruction*> instructions = it->second; auto& instructions = it.second;
bool removeSingletons = false; bool removeSingletons = false;
vector<Instruction*> remain; vector<Instruction*> remain;
for (vector<Instruction*>::iterator lit = instructions.begin(); lit != instructions.end(); lit++) { for (auto instruction : instructions) {
Instruction* instruction = *lit;
if (removeSingletons && instruction->isSingleton()) { if (removeSingletons && instruction->isSingleton()) {
delete instruction; delete instruction;
continue; continue;
@@ -2238,6 +2256,11 @@ result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageF
instruction->isSingleton()?readMessageFunc:NULL); instruction->isSingleton()?readMessageFunc:NULL);
if (result != RESULT_OK) { if (result != RESULT_OK) {
overallResult = result; overallResult = result;
log << "error resolving condition for \"" << instruction->getDestination() << "\": "
<< getResultCode(result);
if (!errorDescription.empty()) {
log << " " << errorDescription;
}
} else if (condition->isTrue()) { } else if (condition->isTrue()) {
execute = true; execute = true;
} }
@@ -2268,13 +2291,13 @@ result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageF
} }
} }
if (remain.empty()) { if (remain.empty()) {
remove.push_back(it->first); remove.push_back(it.first);
} else { } else {
it->second = remain; it.second = remain;
} }
} }
for (vector<string>::iterator it = remove.begin(); it != remove.end(); it++) { for (auto it : remove) {
m_instructions.erase(*it); m_instructions.erase(it);
} }
return overallResult; return overallResult;
} }
@@ -2289,11 +2312,15 @@ void MessageMap::addLoadedFile(symbol_t address, string file, string comment) {
} }
} }
vector<string>& MessageMap::getLoadedFiles(symbol_t address) { const vector<string>& MessageMap::getLoadedFiles(symbol_t address) const {
return m_loadedFiles[address]; auto files = m_loadedFiles.find(address);
if (files != m_loadedFiles.end()) {
return files->second;
}
return s_noFiles;
} }
vector<string> MessageMap::getLoadedFiles() { vector<string> MessageMap::getLoadedFiles() const {
vector<string> ret; vector<string> ret;
for (auto& loadedFile : m_loadedFileInfos) { for (auto& loadedFile : m_loadedFileInfos) {
ret.push_back(loadedFile.first); ret.push_back(loadedFile.first);
@@ -2301,8 +2328,8 @@ vector<string> MessageMap::getLoadedFiles() {
return ret; return ret;
} }
bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* hash, size_t* size, time_t* time) { bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* hash, size_t* size, time_t* time) const {
map<string, LoadedFileInfo>::iterator it = m_loadedFileInfos.find(filename); auto it = m_loadedFileInfos.find(filename);
if (it == m_loadedFileInfos.end()) { if (it == m_loadedFileInfos.end()) {
comment = ""; comment = "";
hash = size = 0; hash = size = 0;
@@ -2322,8 +2349,8 @@ bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* has
return true; return true;
} }
vector<Message*>* MessageMap::getByKey(const uint64_t key) { const vector<Message*>* MessageMap::getByKey(const uint64_t key) const {
map<uint64_t, vector<Message*> >::iterator it = m_messagesByKey.find(key); auto it = m_messagesByKey.find(key);
if (it != m_messagesByKey.end()) { if (it != m_messagesByKey.end()) {
return &it->second; return &it->second;
} }
@@ -2331,7 +2358,7 @@ vector<Message*>* MessageMap::getByKey(const uint64_t key) {
} }
Message* MessageMap::find(const string& circuit, const string& name, const string& levels, const bool isWrite, Message* MessageMap::find(const string& circuit, const string& name, const string& levels, const bool isWrite,
const bool isPassive) { const bool isPassive) const {
string lcircuit = circuit; string lcircuit = circuit;
FileReader::tolower(lcircuit); FileReader::tolower(lcircuit);
string lname = name; string lname = name;
@@ -2345,7 +2372,7 @@ Message* MessageMap::find(const string& circuit, const string& name, const strin
} else { } else {
continue; // not allowed without circuit continue; // not allowed without circuit
} }
map<string, vector<Message*> >::iterator it = m_messagesByName.find(key); auto 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 && message->hasLevel(levels)) { if (message && message->hasLevel(levels)) {
@@ -2359,7 +2386,7 @@ Message* MessageMap::find(const string& circuit, const string& name, const strin
deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const string& levels, deque<Message*> MessageMap::findAll(const string& circuit, const string& name, const string& levels,
const bool completeMatch, const bool withRead, const bool withWrite, const bool withPassive, const bool completeMatch, const bool withRead, const bool withWrite, const bool withPassive,
const bool includeEmptyLevel, const bool onlyAvailable, const bool includeEmptyLevel, const bool onlyAvailable,
const time_t since, const time_t until) { const time_t since, const time_t until) const {
deque<Message*> ret; deque<Message*> ret;
string lcircuit = circuit; string lcircuit = circuit;
FileReader::tolower(lcircuit); FileReader::tolower(lcircuit);
@@ -2368,12 +2395,11 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
bool checkCircuit = lcircuit.length() > 0; bool checkCircuit = lcircuit.length() > 0;
bool checkLevel = levels != "*"; bool checkLevel = levels != "*";
bool checkName = lname.length() > 0; bool checkName = lname.length() > 0;
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) { for (auto it : m_messagesByName) {
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 (auto message : it.second) {
Message* message = *msgIt;
if (checkLevel && !message->hasLevel(levels, includeEmptyLevel)) { if (checkLevel && !message->hasLevel(levels, includeEmptyLevel)) {
continue; continue;
} }
@@ -2415,7 +2441,7 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
} }
} }
if (!onlyAvailable || message->isAvailable()) { if (!onlyAvailable || message->isAvailable()) {
ret.push_back(*msgIt); ret.push_back(message);
} }
} }
} }
@@ -2424,7 +2450,7 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
} }
Message* MessageMap::find(MasterSymbolString& master, bool anyDestination, Message* MessageMap::find(MasterSymbolString& master, bool anyDestination,
const bool withRead, const bool withWrite, const bool withPassive, const bool onlyAvailable) { const bool withRead, const bool withWrite, const bool withPassive, const bool onlyAvailable) const {
if (master.size() >= 5 && master[4] == 0 && anyDestination && master[2] == 0x07 && master[3] == 0x04) { if (master.size() >= 5 && master[4] == 0 && anyDestination && master[2] == 0x07 && master[3] == 0x04) {
return m_scanMessage; return m_scanMessage;
} }
@@ -2448,7 +2474,7 @@ Message* MessageMap::find(MasterSymbolString& master, bool anyDestination,
} }
} }
} }
map<uint64_t , vector<Message*> >::iterator it; map<uint64_t, vector<Message*> >::const_iterator it;
if (withPassive) { if (withPassive) {
it = m_messagesByKey.find(key); it = m_messagesByKey.find(key);
if (it != m_messagesByKey.end()) { if (it != m_messagesByKey.end()) {
@@ -2596,17 +2622,16 @@ Message* MessageMap::getNextPoll() {
return ret; return ret;
} }
void MessageMap::dump(ostream& output, bool withConditions) { void MessageMap::dump(ostream& output, bool withConditions) const {
bool first = true; bool first = true;
Message::dumpHeader(output, NULL); Message::dumpHeader(output, NULL);
output << endl; output << endl;
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) { for (auto it : m_messagesByName) {
if (it->first[0] == '-') { // skip instances stored multiple times (key starting with "-") if (it.first[0] == '-') { // skip instances stored multiple times (key starting with "-")
continue; continue;
} }
if (m_addAll) { if (m_addAll) {
for (vector<Message*>::iterator mit = it->second.begin(); mit != it->second.end(); mit++) { for (auto message : it.second) {
Message* message = *mit;
if (!message) { if (!message) {
continue; continue;
} }
@@ -2618,7 +2643,7 @@ void MessageMap::dump(ostream& output, bool withConditions) {
message->dump(output, NULL, withConditions); message->dump(output, NULL, withConditions);
} }
} else { } else {
Message* message = getFirstAvailable(it->second); Message* message = getFirstAvailable(it.second);
if (!message) { if (!message) {
continue; continue;
} }
+82 -96
View File
@@ -108,7 +108,7 @@ class MessageMap;
/** /**
* Defines parameters of a message sent or received on the bus. * Defines parameters of a message sent or received on the bus.
*/ */
class Message { class Message : public AttributedItem {
friend class MessageMap; friend class MessageMap;
public: public:
/** /**
@@ -119,7 +119,7 @@ class Message {
* @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,
* false if message can be initiated by any participant. * false if message can be initiated by any participant.
* @param comment the comment. * @param attributes the additional named attributes.
* @param srcAddress the source address, or @a SYN for any (only relevant if passive). * @param srcAddress the source address, or @a SYN for any (only relevant if passive).
* @param dstAddress the destination address, or @a SYN for any (set later). * @param dstAddress the destination address, or @a SYN for any (set later).
* @param id the primary, secondary, and optional further ID bytes. * @param id the primary, secondary, and optional further ID bytes.
@@ -129,10 +129,10 @@ class Message {
* @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 level, 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 map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress, const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id, const vector<symbol_t> id,
DataField* data, const bool deleteData, const DataField* data, const bool deleteData,
const size_t pollPriority = 0, const size_t pollPriority = 0,
Condition* condition = NULL); Condition* condition = NULL);
@@ -151,7 +151,7 @@ class Message {
*/ */
Message(const string circuit, const string level, const string name, Message(const string circuit, const string level, const string name,
const symbol_t pb, const symbol_t sb, const symbol_t pb, const symbol_t sb,
const bool broadcast, DataField* data, const bool deleteData); const bool broadcast, const DataField* data, const bool deleteData);
public: public:
@@ -184,6 +184,15 @@ class Message {
static uint64_t createKey(MasterSymbolString& master, static uint64_t createKey(MasterSymbolString& master,
size_t maxIdLength, bool anyDestination = false); size_t maxIdLength, bool anyDestination = false);
/**
* Calculate the key for a scan message.
* @param pb the primary ID byte.
* @param sb the secondary ID byte.
* @param broadcast true for broadcast scan message, false for scan message to be sent to a slave address.
* @return the key for the scan message.
*/
static uint64_t createKey(const symbol_t pb, const symbol_t sb, const bool broadcast);
/** /**
* Get the length field from the key. * Get the length field from the key.
* @param key the key. * @param key the key.
@@ -243,7 +252,7 @@ class Message {
* Return whether this is a special scanning @a Message instance. * Return whether this is a special scanning @a Message instance.
* @return whether this is a special scanning @a Message instance. * @return whether this is a special scanning @a Message instance.
*/ */
bool isScanMessage() { return m_isScanMessage; } bool isScanMessage() const { return m_isScanMessage; }
/** /**
* Derive a new @a Message from this message. * Derive a new @a Message from this message.
@@ -253,7 +262,7 @@ class Message {
* @return the derived @a Message instance. * @return the derived @a Message instance.
*/ */
virtual Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN, virtual Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
const string circuit = ""); const string circuit = "") const;
/** /**
* Derive a new @a Message from this message. * Derive a new @a Message from this message.
@@ -261,7 +270,7 @@ class Message {
* @param extendCircuit whether to extend the current circuit name with a dot and the new destination address in hex. * @param extendCircuit whether to extend the current circuit name with a dot and the new destination address in hex.
* @return the derived @a ScanMessage instance. * @return the derived @a ScanMessage instance.
*/ */
Message* derive(const symbol_t dstAddress, const bool extendCircuit); Message* derive(const symbol_t dstAddress, const bool extendCircuit) const;
/** /**
* Get the optional circuit name. * Get the optional circuit name.
@@ -282,7 +291,7 @@ class Message {
* level to check. * level to check.
* @return true when access is granted. * @return true when access is granted.
*/ */
bool hasLevel(const string levels, bool includeEmpty = true) { bool hasLevel(const string levels, bool includeEmpty = true) const {
return m_level.empty() ? (includeEmpty || levels.empty()) : checkLevel(m_level, levels); return m_level.empty() ? (includeEmpty || levels.empty()) : checkLevel(m_level, levels);
} }
@@ -294,18 +303,12 @@ class Message {
*/ */
static bool checkLevel(const string level, const string checkLevels); static bool checkLevel(const string level, const string checkLevels);
/**
* Get the message name (unique within the same circuit and type).
* @return the message name (unique within the same circuit and type).
*/
string getName() const { return m_name; }
/** /**
* Get the specified field name. * Get the specified field name.
* @param fieldIndex the index of the field. * @param fieldIndex the index of the field.
* @return the field name, or the index as string if not unique or not available. * @return the field name, or the index as string if not unique or not available.
*/ */
virtual string getFieldName(ssize_t fieldIndex) const { return m_data->getName(fieldIndex); } virtual string getFieldName(const ssize_t fieldIndex) const { return m_data->getName(fieldIndex); }
/** /**
* Get whether this is a write message. * Get whether this is a write message.
@@ -320,12 +323,6 @@ class Message {
*/ */
bool isPassive() const { return m_isPassive; } bool isPassive() const { return m_isPassive; }
/**
* Get the comment.
* @return the comment.
*/
string getComment() const { return m_comment; }
/** /**
* Get the source address. * Get the source address.
* @return the source address, or @a SYN for any. * @return the source address, or @a SYN for any.
@@ -361,7 +358,7 @@ class Message {
* @param id the ID bytes to check against. * @param id the ID bytes to check against.
* @return true if the full command ID starts with the given value. * @return true if the full command ID starts with the given value.
*/ */
bool checkIdPrefix(vector<symbol_t>& id); bool checkIdPrefix(const vector<symbol_t>& id) const;
/** /**
* Check the ID against the master @a SymbolString data. * Check the ID against the master @a SymbolString data.
@@ -369,27 +366,27 @@ class Message {
* @param index the variable in which to store the message part index, or NULL to ignore. * @param index the variable in which to store the message part index, or NULL to ignore.
* @return true if the ID matches, false otherwise. * @return true if the ID matches, false otherwise.
*/ */
virtual bool checkId(MasterSymbolString& master, size_t* index = NULL); virtual bool checkId(const MasterSymbolString& master, size_t* index = NULL) const;
/** /**
* Check the ID against the other @a Message. * Check the ID against the other @a Message.
* @param other the other @a Message to check against. * @param other the other @a Message to check against.
* @return true if the ID matches, false otherwise. * @return true if the ID matches, false otherwise.
*/ */
virtual bool checkId(Message& other); virtual bool checkId(Message& other) const;
/** /**
* Return the key for storing in @a MessageMap. * Return the key for storing in @a MessageMap.
* @return the key for storing in @a MessageMap. * @return the key for storing in @a MessageMap.
*/ */
uint64_t getKey() { return m_key; } uint64_t getKey() const { return m_key; }
/** /**
* Return the derived key for storing in @a MessageMap. * Return the derived key for storing in @a MessageMap.
* @param dstAddress the destination address for the derivation. * @param dstAddress the destination address for the derivation.
* @return the derived key for storing in @a MessageMap. * @return the derived key for storing in @a MessageMap.
*/ */
uint64_t getDerivedKey(const symbol_t dstAddress); uint64_t getDerivedKey(const symbol_t dstAddress) const;
/** /**
* Get the polling priority, or 0 for no polling at all. * Get the polling priority, or 0 for no polling at all.
@@ -427,12 +424,12 @@ class Message {
* @param numeric true for a numeric field, false for a string field. * @param numeric true for a numeric field, false for a string field.
* @return true if the field is available. * @return true if the field is available.
*/ */
bool hasField(const char* fieldName, bool numeric = true); bool hasField(const char* fieldName, bool numeric = true) const;
/** /**
* @return the number of parts this message is composed of. * @return the number of parts this message is composed of.
*/ */
virtual size_t getCount() { return 1; } virtual size_t getCount() const { return 1; }
/** /**
* Prepare the master @a SymbolString for sending a query or command to the bus. * Prepare the master @a SymbolString for sending a query or command to the bus.
@@ -505,7 +502,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t decodeLastMasterData(ostringstream& output, OutputFormat outputFormat = 0, virtual result_t decodeLastMasterData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1); bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
/** /**
* Decode the value from the last stored slave data. * Decode the value from the last stored slave data.
@@ -517,7 +514,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat = 0, virtual result_t decodeLastSlaveData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1); bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
/** /**
* Decode the value from the last stored data. * Decode the value from the last stored data.
@@ -529,7 +526,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat = 0, virtual result_t decodeLastData(ostringstream& output, OutputFormat outputFormat = 0,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1); bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const;
/** /**
* Decode a particular numeric field value from the last stored data. * Decode a particular numeric field value from the last stored data.
@@ -538,44 +535,44 @@ class Message {
* @param fieldIndex the optional index of the named field, or -1. * @param fieldIndex the optional index of the named field, or -1.
* @return @a RESULT_OK on success, or an error code. * @return @a RESULT_OK on success, or an error code.
*/ */
virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex = -1); virtual result_t decodeLastDataNumField(unsigned int& output, const char* fieldName, ssize_t fieldIndex = -1) const;
/** /**
* Get the last seen master data. * Get the last seen master data.
* @return the last seen @a MasterSymbolString. * @return the last seen @a MasterSymbolString.
*/ */
MasterSymbolString& getLastMasterData() { return m_lastMasterData; } const MasterSymbolString& getLastMasterData() const { return m_lastMasterData; }
/** /**
* Get the last seen slave data. * Get the last seen slave data.
* @return the last seen @a SlaveSymbolString. * @return the last seen @a SlaveSymbolString.
*/ */
SlaveSymbolString& getLastSlaveData() { return m_lastSlaveData; } const SlaveSymbolString& getLastSlaveData() const { return m_lastSlaveData; }
/** /**
* Get the time when this message was last seen with reasonable data. * Get the time when this message was last seen with reasonable data.
* @return the time when this message was last seen, or 0. * @return the time when this message was last seen, or 0.
*/ */
time_t getLastUpdateTime() { return m_lastUpdateTime; } time_t getLastUpdateTime() const { return m_lastUpdateTime; }
/** /**
* Get the time when the message data was last changed. * Get the time when the message data was last changed.
* @return the time when the message data was last changed, or 0 if this message was not decoded yet. * @return the time when the message data was last changed, or 0 if this message was not decoded yet.
*/ */
time_t getLastChangeTime() { return m_lastChangeTime; } time_t getLastChangeTime() const { return m_lastChangeTime; }
/** /**
* Get the time when this message was last polled for. * Get the time when this message was last polled for.
* @return the time when this message was last polled for, or 0 for never. * @return the time when this message was last polled for, or 0 for never.
*/ */
time_t getLastPollTime() { return m_lastPollTime; } time_t getLastPollTime() const { return m_lastPollTime; }
/** /**
* Return whether this @a Message needs to be polled after the other one. * Return whether this @a Message needs to be polled after the other one.
* @param other the other @a Message to compare with. * @param other the other @a Message to compare with.
* @return true if this @a Message needs to be polled after the other one. * @return true if this @a Message needs to be polled after the other one.
*/ */
bool isLessPollWeight(const Message* other); bool isLessPollWeight(const Message* other) const;
/** /**
* Write the message definition header or parts of it to the @a ostream. * Write the message definition header or parts of it to the @a ostream.
@@ -590,7 +587,7 @@ class Message {
* @param fieldIds the list of field IDs to write, or NULL for all (see @p MESSAGEFIELD_TYPE constants). * @param fieldIds the list of field IDs to write, or NULL for all (see @p MESSAGEFIELD_TYPE 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>* fieldIds = NULL, bool withConditions = false); void dump(ostream& output, vector<size_t>* fieldIds = NULL, bool withConditions = false) const;
/** /**
* Write the specified field to the @a ostream. * Write the specified field to the @a ostream.
@@ -598,7 +595,7 @@ class Message {
* @param fieldId the field ID to write (see @p MESSAGEFIELD_TYPE constants). * @param fieldId the field ID to write (see @p MESSAGEFIELD_TYPE constants).
* @param withConditions whether to include the optional conditions prefix. * @param withConditions whether to include the optional conditions prefix.
*/ */
virtual void dumpField(ostream& output, size_t fieldId, bool withConditions = false); virtual void dumpField(ostream& output, size_t fieldId, bool withConditions = false) const;
protected: protected:
@@ -608,9 +605,6 @@ class Message {
/** the optional access level. */ /** the optional access level. */
const string m_level; const string m_level;
/** the message name (unique within the same circuit and type). */
const string m_name;
/** whether this is a write message. */ /** whether this is a write message. */
const bool m_isWrite; const bool m_isWrite;
@@ -618,8 +612,8 @@ class Message {
* false if message can be initiated by any participant. */ * false if message can be initiated by any participant. */
const bool m_isPassive; const bool m_isPassive;
/** the comment. */ /** the additional named attributes. */
const string m_comment; const map<string, string> m_attributes;
/** the source address, or @a SYN for any (only relevant if passive). */ /** the source address, or @a SYN for any (only relevant if passive). */
const symbol_t m_srcAddress; const symbol_t m_srcAddress;
@@ -628,7 +622,7 @@ class Message {
const symbol_t m_dstAddress; const symbol_t m_dstAddress;
/** the primary, secondary, and optionally further command ID bytes. */ /** the primary, secondary, and optionally further command ID bytes. */
vector<symbol_t> m_id; const vector<symbol_t> m_id;
/** /**
* the key for storing in @a MessageMap. * the key for storing in @a MessageMap.
@@ -651,10 +645,10 @@ class Message {
* <li>bytes 3-0: ID bytes (with cyclic xor if more than 4)</li> * <li>bytes 3-0: ID bytes (with cyclic xor if more than 4)</li>
* </ul> * </ul>
*/ */
uint64_t m_key; const uint64_t m_key;
/** the @a DataField for encoding/decoding the message. */ /** the @a DataField for encoding/decoding the message. */
DataField* m_data; const DataField* m_data;
/** whether to delete the @a DataField during destruction. */ /** whether to delete the @a DataField during destruction. */
const bool m_deleteData; const bool m_deleteData;
@@ -702,7 +696,7 @@ class ChainedMessage : public Message {
* @param level the optional access level. * @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 attributes the additional named attributes.
* @param srcAddress the source address, or @a SYN for any (only relevant if passive). * @param srcAddress the source address, or @a SYN for any (only relevant if passive).
* @param dstAddress the destination address, or @a SYN for any (set later). * @param dstAddress the destination address, or @a SYN for any (set later).
* @param id the primary, secondary, and optional further ID bytes common to each part of the chain. * @param id the primary, secondary, and optional further ID bytes common to each part of the chain.
@@ -714,11 +708,11 @@ class ChainedMessage : public Message {
* @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 level, const string name, ChainedMessage(const string circuit, const string level, const string name,
const bool isWrite, const string comment, const bool isWrite, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress, const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id, const vector<symbol_t> id,
vector< vector<symbol_t> > ids, vector<size_t> lengths, vector< vector<symbol_t> > ids, vector<size_t> lengths,
DataField* data, const bool deleteData, const DataField* data, const bool deleteData,
const size_t pollPriority, const size_t pollPriority,
Condition* condition = NULL); Condition* condition = NULL);
@@ -726,19 +720,19 @@ class ChainedMessage : public Message {
// @copydoc // @copydoc
Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN, Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
const string circuit = "") override; const string circuit = "") const override;
// @copydoc // @copydoc
size_t getIdLength() const override { return m_ids[0].size() - 2; } size_t getIdLength() const override { return m_ids[0].size() - 2; }
// @copydoc // @copydoc
bool checkId(MasterSymbolString& master, size_t* index = NULL) override; bool checkId(const MasterSymbolString& master, size_t* index = NULL) const override;
// @copydoc // @copydoc
bool checkId(Message& other) override; bool checkId(Message& other) const override;
// @copydoc // @copydoc
size_t getCount() override { return m_ids.size(); } size_t getCount() const override { return m_ids.size(); }
protected: protected:
@@ -765,7 +759,7 @@ class ChainedMessage : public Message {
protected: protected:
// @copydoc // @copydoc
void dumpField(ostream& output, size_t fieldId, bool withConditions = false) override; void dumpField(ostream& output, size_t fieldId, bool withConditions = false) const override;
private: private:
@@ -860,14 +854,14 @@ class Condition {
* @param valueList the @a string with the new list of values. * @param valueList the @a string with the new list of values.
* @return the derived @a SimpleCondition instance, or NULL if the value list is invalid. * @return the derived @a SimpleCondition instance, or NULL if the value list is invalid.
*/ */
virtual SimpleCondition* derive(string valueList) { return NULL; } virtual SimpleCondition* derive(string valueList) const { return NULL; }
/** /**
* Write the condition definition or resolved expression to the @a ostream. * Write the condition definition or resolved expression to the @a ostream.
* @param output the @a ostream to append to. * @param output the @a ostream to append to.
* @param matched true for dumping the matched value if the condition is true, false for dumping the definition. * @param matched true for dumping the matched value if the condition is true, false for dumping the definition.
*/ */
virtual void dump(ostream& output, bool matched = false) = 0; virtual void dump(ostream& output, bool matched = false) const = 0;
/** /**
* Combine this condition with another instance using a logical and. * Combine this condition with another instance using a logical and.
@@ -931,10 +925,10 @@ class SimpleCondition : public Condition {
virtual ~SimpleCondition() {} virtual ~SimpleCondition() {}
// @copydoc // @copydoc
SimpleCondition* derive(string valueList) override; SimpleCondition* derive(string valueList) const override;
// @copydoc // @copydoc
void dump(ostream& output, bool matched = false) override; void dump(ostream& output, bool matched = false) const override;
// @copydoc // @copydoc
CombinedCondition* combineAnd(Condition* other) override; CombinedCondition* combineAnd(Condition* other) override;
@@ -950,7 +944,7 @@ class SimpleCondition : public Condition {
* Return whether the condition is based on a numeric value. * Return whether the condition is based on a numeric value.
* @return whether the condition is based on a numeric value. * @return whether the condition is based on a numeric value.
*/ */
virtual bool isNumeric() { return true; } virtual bool isNumeric() const { return true; }
protected: protected:
@@ -1062,7 +1056,7 @@ class SimpleStringCondition : public SimpleCondition {
virtual ~SimpleStringCondition() {} virtual ~SimpleStringCondition() {}
// @copydoc // @copydoc
bool isNumeric() override { return false; } bool isNumeric() const override { return false; }
protected: protected:
@@ -1093,7 +1087,7 @@ class CombinedCondition : public Condition {
virtual ~CombinedCondition() {} virtual ~CombinedCondition() {}
// @copydoc // @copydoc
void dump(ostream& output, bool matched = false) override; void dump(ostream& output, bool matched = false) const override;
// @copydoc // @copydoc
CombinedCondition* combineAnd(Condition* other) override { m_conditions.push_back(other); return this; } CombinedCondition* combineAnd(Condition* other) override { m_conditions.push_back(other); return this; }
@@ -1124,7 +1118,7 @@ class Instruction {
* executed for the same source file. * executed for the same source file.
* @param defaults the mapped definition defaults. * @param defaults the mapped definition defaults.
*/ */
Instruction(Condition* condition, const bool singleton, map<string, string>& defaults) Instruction(Condition* condition, const bool singleton, const map<string, string>& defaults)
: m_condition(condition), m_singleton(singleton), m_defaults(defaults) { } : m_condition(condition), m_singleton(singleton), m_defaults(defaults) { }
/** /**
@@ -1158,13 +1152,13 @@ class Instruction {
* @return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed * @return whether this @a Instruction belongs to a set of instructions of which only the first one may be executed
* for the same source file. * for the same source file.
*/ */
bool isSingleton() { return m_singleton; } bool isSingleton() const { return m_singleton; }
/** /**
* Return a string describing the destination from the stored default values. * Return a string describing the destination from the stored default values.
* @return a string describing the destination. * @return a string describing the destination.
*/ */
string getDestination(); string getDestination() const;
/** /**
* Execute the instruction. * Execute the instruction.
@@ -1182,7 +1176,7 @@ class Instruction {
/** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the /** whether this @a Instruction belongs to a set of instructions of which only the first one may be executed for the
* same source file. */ * same source file. */
bool m_singleton; const bool m_singleton;
protected: protected:
@@ -1227,17 +1221,6 @@ class LoadInstruction : public Instruction {
*/ */
class LoadedFileInfo { class LoadedFileInfo {
public: public:
/**
* Constructor.
* @param comment the optional comment for the file.
* @param hash the hash of the file.
* @param size the normalized size of the file.
* @param time the modification time of the file.
*/
/*explicit LoadedFileInfo(string comment, size_t hash, size_t size, time_t time)
: m_comment(comment), m_hash(hash), m_size(size), m_time(time) {}
LoadedFileInfo(const LoadedFileInfo& copyFrom)
: m_comment(copyFrom.m_comment), m_hash(copyFrom.m_hash), m_size(copyFrom.m_size), m_time(copyFrom.m_time) {}*/
/** the optional comment for the file. */ /** the optional comment for the file. */
string m_comment; string m_comment;
@@ -1293,7 +1276,7 @@ class MessageMap : public MappedFileReader {
result_t add(Message* message, bool storeByName = true); result_t add(Message* message, bool storeByName = true);
// @copydoc // @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription) override; result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc // @copydoc
result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows, result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
@@ -1311,7 +1294,7 @@ class MessageMap : public MappedFileReader {
// @copydoc // @copydoc
bool extractDefaultsFromFilename(string filename, map<string, string>& defaults, bool extractDefaultsFromFilename(string filename, map<string, string>& defaults,
symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) override; symbol_t* destAddress = NULL, unsigned int* software = NULL, unsigned int* hardware = NULL) const override;
// @copydoc // @copydoc
result_t readFromFile(const string filename, string& errorDescription, bool verbose = false, result_t readFromFile(const string filename, string& errorDescription, bool verbose = false,
@@ -1332,7 +1315,7 @@ class MessageMap : public MappedFileReader {
* Return whether additional scan @a Message instances are available. * Return whether additional scan @a Message instances are available.
* @return whether additional scan @a Message instances are available. * @return whether additional scan @a Message instances are available.
*/ */
bool hasAdditionalScanMessages() { return m_additionalScanMessages; } bool hasAdditionalScanMessages() const { return m_additionalScanMessages; }
/** /**
* Resolve all @a Condition instances. * Resolve all @a Condition instances.
@@ -1374,13 +1357,13 @@ class MessageMap : public MappedFileReader {
* @param address the slave address. * @param address the slave address.
* @return the loaded configuration files (list of file names with relative path). * @return the loaded configuration files (list of file names with relative path).
*/ */
vector<string>& getLoadedFiles(symbol_t address); const vector<string>& getLoadedFiles(symbol_t address) const;
/** /**
* Get all loaded files. * Get all loaded files.
* @return the loaded configuration files (list of file names with relative path). * @return the loaded configuration files (list of file names with relative path).
*/ */
vector<string> getLoadedFiles(); vector<string> getLoadedFiles() const;
/** /**
* Get the infos for a loaded file. * Get the infos for a loaded file.
@@ -1392,7 +1375,7 @@ class MessageMap : public MappedFileReader {
* @return true if the file info was found, false otherwise. * @return true if the file info was found, false otherwise.
*/ */
bool getLoadedFileInfo(string filename, string& comment, size_t* hash = NULL, size_t* size = NULL, bool getLoadedFileInfo(string filename, string& comment, size_t* hash = NULL, size_t* size = NULL,
time_t* time = NULL); time_t* time = NULL) const;
/** /**
* Get the stored @a Message instances for the key. * Get the stored @a Message instances for the key.
@@ -1400,7 +1383,7 @@ class MessageMap : public MappedFileReader {
* @return the found @a Message instances, or NULL. * @return the found @a Message instances, or NULL.
* Note: the caller may not free the returned instances. * Note: the caller may not free the returned instances.
*/ */
vector<Message*>* getByKey(const uint64_t key); const vector<Message*>* getByKey(const uint64_t key) const;
/** /**
* Find the @a Message instance for the specified circuit and name. * Find the @a Message instance for the specified circuit and name.
@@ -1413,7 +1396,7 @@ class MessageMap : public MappedFileReader {
* 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 string& levels, const bool isWrite, Message* find(const string& circuit, const string& name, const string& levels, const bool isWrite,
const bool isPassive = false); const bool isPassive = false) const;
/** /**
* 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.
@@ -1439,7 +1422,7 @@ class MessageMap : public MappedFileReader {
deque<Message*> findAll(const string& circuit, const string& name, const string& levels, deque<Message*> findAll(const string& circuit, const string& name, const string& levels,
const bool completeMatch = true, const bool withRead = true, const bool withWrite = false, const bool completeMatch = true, const bool withRead = true, const bool withWrite = false,
const bool withPassive = false, const bool includeEmptyLevel = true, const bool onlyAvailable = true, const bool withPassive = false, const bool includeEmptyLevel = true, const bool onlyAvailable = true,
const time_t since = 0, const time_t until = 0); const time_t since = 0, const time_t until = 0) const;
/** /**
* Find the @a Message instance for the specified master data. * Find the @a Message instance for the specified master data.
@@ -1454,7 +1437,7 @@ class MessageMap : public MappedFileReader {
* Note: the caller may not free the returned instance. * Note: the caller may not free the returned instance.
*/ */
Message* find(MasterSymbolString& master, bool anyDestination = false, const bool withRead = true, Message* find(MasterSymbolString& master, bool anyDestination = false, const bool withRead = true,
const bool withWrite = true, const bool withPassive = true, const bool onlyAvailable = true); const bool withWrite = true, const bool withPassive = true, const bool onlyAvailable = true) const;
/** /**
* Invalidate cached data of the @a Message and all other instances with a matching name key. * Invalidate cached data of the @a Message and all other instances with a matching name key.
@@ -1478,25 +1461,25 @@ class MessageMap : public MappedFileReader {
* Get the number of all stored @a Message instances. * Get the number of all stored @a Message instances.
* @return the the number of all stored @a Message instances. * @return the the number of all stored @a Message instances.
*/ */
size_t size() { return m_messageCount; } size_t size() const { return m_messageCount; }
/** /**
* Get the number of stored conditional @a Message instances. * Get the number of stored conditional @a Message instances.
* @return the the number of stored conditional @a Message instances. * @return the the number of stored conditional @a Message instances.
*/ */
size_t sizeConditional() { return m_conditionalMessageCount; } size_t sizeConditional() const { return m_conditionalMessageCount; }
/** /**
* Get the number of stored passive @a Message instances. * Get the number of stored passive @a Message instances.
* @return the the number of stored passive @a Message instances. * @return the the number of stored passive @a Message instances.
*/ */
size_t sizePassive() { return m_passiveMessageCount; } size_t sizePassive() const { return m_passiveMessageCount; }
/** /**
* Get the number of stored @a Message instances with a poll priority. * Get the number of stored @a Message instances with a poll priority.
* @return the the number of stored @a Message instances with a poll priority. * @return the the number of stored @a Message instances with a poll priority.
*/ */
size_t sizePoll() { return m_pollMessages.size(); } size_t sizePoll() const { return m_pollMessages.size(); }
/** /**
* Get the next @a Message to poll. * Get the next @a Message to poll.
@@ -1509,23 +1492,26 @@ class MessageMap : public MappedFileReader {
* Get the number of stored @a Condition instances. * Get the number of stored @a Condition instances.
* @return the number of stored @a Condition instances. * @return the number of stored @a Condition instances.
*/ */
size_t sizeConditions() { return m_conditions.size(); } size_t sizeConditions() const { return m_conditions.size(); }
/** /**
* Get the stored @a Condition instances. * Get the stored @a Condition instances.
* @return the @a Condition instances by filename and condition name. * @return the @a Condition instances by filename and condition name.
*/ */
map<string, Condition*>& getConditions() { return m_conditions; } const map<string, Condition*>& getConditions() const { return m_conditions; }
/** /**
* Write the message definitions to the @a ostream. * Write the message definitions to the @a ostream.
* @param output the @a ostream to append the formatted messages to. * @param output the @a ostream to append the formatted messages to.
* @param withConditions whether to include the optional conditions prefix. * @param withConditions whether to include the optional conditions prefix.
*/ */
void dump(ostream& output, bool withConditions = false); void dump(ostream& output, const bool withConditions = false) const;
private: private:
/** empty vector for @a getLoadedFiles(). */
static vector<string> s_noFiles;
/** whether to add all messages, even if duplicate. */ /** whether to add all messages, even if duplicate. */
const bool m_addAll; const bool m_addAll;
+1 -1
View File
@@ -144,7 +144,7 @@ result_t SymbolString::parseHexEscaped(const string& str) {
return inEscape ? RESULT_ERR_ESC : RESULT_OK; return inEscape ? RESULT_ERR_ESC : RESULT_OK;
} }
const string SymbolString::getStr(size_t skipFirstSymbols) { const string SymbolString::getStr(size_t skipFirstSymbols) const {
ostringstream sstr; ostringstream sstr;
for (size_t i = 0; i < m_data.size(); i++) { for (size_t i = 0; i < m_data.size(); i++) {
if (skipFirstSymbols > 0) { if (skipFirstSymbols > 0) {
+14 -1
View File
@@ -156,7 +156,7 @@ class SymbolString {
* @param skipFirstSymbols the number of first symbols to skip. * @param skipFirstSymbols the number of first symbols to skip.
* @return the symbols as hex string. * @return the symbols as hex string.
*/ */
const string getStr(size_t skipFirstSymbols = 0); const string getStr(size_t skipFirstSymbols = 0) const;
/** /**
* Return a reference to the symbol at the specified index. * Return a reference to the symbol at the specified index.
@@ -245,6 +245,19 @@ class SymbolString {
return m_data.size() < lengthOffset + 1 + ret ? m_data.size() - lengthOffset - 1 : ret; return m_data.size() < lengthOffset + 1 + ret ? m_data.size() - lengthOffset - 1 : ret;
} }
/**
* Return the data byte at the specified index (within DD).
* @param index the index of the data byte (within DD) to return.
* @return the data byte at the specified index, or 0 if not available.
*/
symbol_t dataAt(const size_t index) const {
size_t offset = (m_isMaster ? 5 : 1) + index;
if (offset < m_data.size()) {
return m_data[offset];
}
return 0;
}
/** /**
* Return a reference to the data byte at the specified index (within DD). * Return a reference to the data byte at the specified index (within DD).
* @param index the index of the data byte (within DD) to return. * @param index the index of the data byte (within DD) to return.
+3 -3
View File
@@ -53,7 +53,7 @@ class TestReader : public MappedFileReader {
TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest) TestReader(DataFieldTemplates* templates, bool isSet, bool isMasterDest)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest), : MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
m_fields(NULL) {} m_fields(NULL) {}
result_t getFieldMap(vector<string>& row, string& errorDescription) override { result_t getFieldMap(vector<string>& row, string& errorDescription) const override {
if (row.empty()) { if (row.empty()) {
row.push_back("*name"); row.push_back("*name");
row.push_back("part"); row.push_back("part");
@@ -84,7 +84,7 @@ class TestReader : public MappedFileReader {
const bool m_isSet; const bool m_isSet;
const bool m_isMasterDest; const bool m_isMasterDest;
public: public:
DataField* m_fields; const DataField* m_fields;
}; };
@@ -509,7 +509,7 @@ int main() {
string errorDescription; string errorDescription;
vector<string> row; vector<string> row;
templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row); templates->readLineFromStream(dummystr, errorDescription, "inline", lineNo, row);
DataField* fields = NULL; const DataField* fields = NULL;
for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) { for (size_t i = 0; i < sizeof(checks) / sizeof(checks[0]); i++) {
string check[5] = checks[i]; string check[5] = checks[i];
istringstream isstr(check[0]); istringstream isstr(check[0]);
+1 -1
View File
@@ -82,7 +82,7 @@ class NoopReader : public FileReader {
class TestReader : public MappedFileReader { class TestReader : public MappedFileReader {
public: public:
TestReader(size_t expectedCols) : MappedFileReader::MappedFileReader(false), m_expectedCols(expectedCols) {} TestReader(size_t expectedCols) : MappedFileReader::MappedFileReader(false), m_expectedCols(expectedCols) {}
result_t getFieldMap(vector<string>& row, string& errorDescription) override { result_t getFieldMap(vector<string>& row, string& errorDescription) const override {
if (row.size() == m_expectedCols) { if (row.size() == m_expectedCols) {
cout << "get field map: split OK" << endl; cout << "get field map: split OK" << endl;
return RESULT_OK; return RESULT_OK;