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.
* @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) {
bool first = true;
string in = input->getStr(input->getDataOffset());
@@ -225,7 +225,7 @@ bool decodeType(DataType* type, SymbolString *input, size_t length,
unsigned int value = 0;
if (type->readRawValue(*input, offset, length, value) == RESULT_OK) {
out.str("");
out << DataField::getDayName(reinterpret_cast<NumberDataType*>(type)->getMinValue()+value);
out << DataField::getDayName(reinterpret_cast<const NumberDataType*>(type)->getMinValue()+value);
}
}
if (first) {
@@ -288,8 +288,8 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
if (remain == 0) {
return true;
}
for (map<string, DataType*>::const_iterator it = types->begin(); it != types->end(); it++) {
DataType* baseType = it->second;
for (auto it : *types) {
const DataType* baseType = it.second;
if ((baseType->getBitCount() % 8) != 0 || baseType->isIgnored()) { // skip bit and ignored types
continue;
}
@@ -300,7 +300,7 @@ bool GrabbedMessage::dump(const bool unknown, MessageMap* messages, bool first,
}
if (baseType->isAdjustableLength()) {
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 (firstOnly) {
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()) {
bool first = true;
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);
}
}
vector<string>& loadedFiles = m_messages->getLoadedFiles(address);
const vector<string>& loadedFiles = m_messages->getLoadedFiles(address);
if (!loadedFiles.empty()) {
output << ",\"f\":[";
bool first = true;
+7 -7
View File
@@ -73,7 +73,7 @@ class UserInfo {
* @param user the user name.
* @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.
@@ -81,14 +81,14 @@ class UserInfo {
* @param secret the secret to check.
* @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.
* @param user the user name, or empty for default levels.
* @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.
*/
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.
*/
virtual bool isDataSource() { return false; }
virtual bool isDataSource() const { return false; }
};
@@ -146,7 +146,7 @@ class DataSink : virtual public DataHandler {
virtual ~DataSink() {}
// @copydoc
bool isDataSink() override { return true; }
bool isDataSink() const override { return true; }
/**
* Notify the sink of an updated @a Message.
@@ -187,7 +187,7 @@ class DataSource : virtual public DataHandler {
virtual ~DataSource() {}
// @copydoc
bool isDataSource() override { return true; }
bool isDataSource() const override { return true; }
protected:
+2 -2
View File
@@ -884,9 +884,9 @@ result_t loadScanConfigFile(MessageMap* messages, symbol_t address, string& rela
if (!message) {
return RESULT_ERR_NOTFOUND;
}
SlaveSymbolString& data = message->getLastSlaveData();
const SlaveSymbolString& data = message->getLastSlaveData();
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;
}
DataFieldSet* identFields = DataFieldSet::getIdentFields();
+33 -9
View File
@@ -41,7 +41,7 @@ using std::ifstream;
#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]*
if (row.empty()) {
row.push_back("name");
@@ -735,7 +735,7 @@ string MainLoop::executeRead(vector<string> &args, const string levels) {
if (srcAddress == SYN
&& (message->getLastUpdateTime() + maxAge > now
|| (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());
return slave.getStr();
}
@@ -998,7 +998,7 @@ string MainLoop::executeWrite(vector<string> &args, const string levels) {
getResultCode(ret));
return getResultCode(ret);
}
dstAddress = message->getLastMasterData()[1];
dstAddress = message->getLastMasterData().dataAt(1);
ostringstream result;
if (dstAddress == BROADCAST || isMaster(dstAddress)) {
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") {
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;
} else if (args[argPos] == "-V") {
verbosity |= OF_NAMES|OF_UNITS|OF_COMMENTS|OF_ALL_ATTRS;
} else if (args[argPos] == "-f") {
configFormat = true;
if (hexFormat) {
@@ -1251,12 +1253,12 @@ string MainLoop::executeFind(vector<string> &args, string levels) {
<< " / " << 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();
if (dstAddress != SYN) {
snprintf(str, sizeof(str), "%02x", dstAddress);
} 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 {
snprintf(str, sizeof(str), "any");
}
@@ -1533,7 +1535,7 @@ string MainLoop::executeHelp() {
string MainLoop::executeGet(vector<string> &args, bool& connected) {
result_t ret = RESULT_OK;
bool numeric = false, required = false;
bool numeric = false, required = false, full = false;
OutputFormat verbosity = OF_NAMES;
size_t argPos = 1;
string uri = args[argPos++];
@@ -1583,6 +1585,8 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
}
} else if (qname == "numeric") {
numeric = value.length() == 0 || value == "1";
} else if (qname == "full") {
full = value.length() == 0 || value == "1";
} else if (qname == "required") {
required = value.length() == 0 || value == "1";
} else if (qname == "user") {
@@ -1639,6 +1643,7 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
}
lastCircuit = message->getCircuit();
result << "\n \"" << lastCircuit << "\": {";
// TODO add circuit specific values
first = true;
}
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) << "\"";
size_t pos = (size_t) result.tellp();
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) {
result << "\n }";
} else {
@@ -1671,7 +1677,25 @@ string MainLoop::executeGet(vector<string> &args, bool& connected) {
result << "\n },";
}
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 }";
result << "\n}";
+9 -5
View File
@@ -62,24 +62,28 @@ class UserList : public UserInfo, public MappedFileReader {
virtual ~UserList() {}
// @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription) override;
result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc
result_t addFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
string& errorDescription, const string filename, unsigned int lineNo) override;
// @copydoc
bool hasUser(const string user) override {
bool hasUser(const string user) const override {
return m_userLevels.find(user) != m_userLevels.end();
}
// @copydoc
bool checkSecret(const string user, const string secret) override {
return m_userSecrets.find(user) != m_userSecrets.end() && m_userSecrets[user] == secret;
bool checkSecret(const string user, const string secret) const override {
auto it = m_userSecrets.find(user);
return it != m_userSecrets.end() && it->second == secret;
}
// @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:
/** 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"));
}
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) {
divisor = 1;
}
@@ -53,9 +53,9 @@ result_t TemParamDataType::derive(int divisor, size_t bitCount, NumberDataType*
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,
ostringstream& output, OutputFormat outputFormat) {
ostringstream& output, OutputFormat outputFormat) const {
unsigned int value = 0;
result_t result = readRawValue(input, offset, length, value);
@@ -92,7 +92,7 @@ result_t TemParamDataType::readSymbols(SymbolString& input,
result_t TemParamDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) {
SymbolString& output, size_t* usedLength) const {
unsigned int value;
int grp, num;
string token;
+5 -5
View File
@@ -47,20 +47,20 @@ class TemParamDataType : public NumberDataType {
* @param id the type identifier.
*/
explicit TemParamDataType(const string id)
: NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0) {}
: NumberDataType(id, 16, 0, 0xffff, 0, 0xffff, 0, NULL) {}
// @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
result_t readSymbols(SymbolString& input,
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override;
ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
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)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
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()) {
row.push_back("*name");
row.push_back("part");
@@ -85,11 +85,11 @@ class TestReader : public MappedFileReader {
const bool m_isSet;
const bool m_isMasterDest;
public:
DataField* m_fields;
const DataField* m_fields;
};
int main() {
DataType* type = DataTypeList::getInstance()->get("TEM_P");
const DataType* type = DataTypeList::getInstance()->get("TEM_P");
if (type == NULL) {
cout << "datatype not registered" << endl;
return 1;
@@ -119,7 +119,7 @@ int main() {
string errorDescription;
vector<string> 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++) {
string check[5] = checks[i];
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 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.
*/
class DataField {
class DataField : public AttributedItem {
public:
/**
* Constructs a new instance.
* @param name the field name.
* @param comment the field comment.
* @param attributes the additional named attributes.
*/
DataField(const string name, const string comment)
: m_name(name), m_comment(comment) {}
DataField(const string name, const map<string, string>& attributes)
: AttributedItem(name, attributes) {}
/**
* Constructs a new instance (without additional attributes).
* @param name the field name.
*/
explicit DataField(const string name)
: AttributedItem(name) {}
/**
* Destructor.
@@ -113,7 +211,7 @@ class DataField {
* Clone this instance.
* @return a clone of this instance.
*/
virtual DataField* clone() = 0;
virtual const DataField* clone() const = 0;
/**
* Factory method for creating new instances.
@@ -129,18 +227,10 @@ class DataField {
* Note: the caller needs to free the created instance.
*/
static result_t create(vector< map<string, string> >& rows, string& errorDescription,
DataFieldTemplates* templates, DataField*& returnField,
const bool isWriteMessage,
const bool isTemplate, const bool isBroadcastOrMasterDestination,
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);
DataFieldTemplates* templates, const DataField*& returnField,
const bool isWriteMessage,
const bool isTemplate, const bool isBroadcastOrMasterDestination,
const size_t maxFieldLength = MAX_POS);
/**
* Return the name of the specified day.
@@ -155,42 +245,33 @@ class DataField {
* @param maxLength the maximum length for calculating remainder of input.
* @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.
* @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 unit the value unit, or empty to use this fields unit (if applicable).
* @param attributes the additional named attributes to override.
* @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 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.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t derive(string name, string comment,
string unit, const PartType partType,
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) = 0;
virtual result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const = 0;
/**
* Get the specified field name.
* @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.
*/
virtual string getName(ssize_t fieldIndex = -1) { return m_name; }
/**
* Get the field comment.
* @return the field comment.
*/
string getComment() const { return m_comment; }
virtual string getName(const ssize_t fieldIndex = -1) const { return m_name; }
/**
* Dump the field settings to the output.
* @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.
@@ -198,7 +279,7 @@ class DataField {
* @param numeric true for a numeric field, false for a string field.
* @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.
@@ -212,8 +293,8 @@ class DataField {
* not match or ignored, or due to @a fieldName or @a fieldIndex),
* or an error code.
*/
virtual result_t read(SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) = 0;
virtual result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
/**
* 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 an error code.
*/
virtual result_t read(SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) = 0;
virtual result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const = 0;
/**
* 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.
*/
virtual result_t write(istringstream& input, SymbolString& data,
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) = 0;
protected:
/** the field name. */
const string m_name;
/** the field comment. */
const string m_comment;
size_t offset, char separator = UI_FIELD_SEPARATOR, size_t* length = NULL) const = 0;
};
@@ -263,18 +336,15 @@ class SingleDataField : public DataField {
/**
* Constructs a new instance.
* @param name the field name.
* @param comment the field comment.
* @param unit the value unit.
* @param attributes the additional named attributes.
* @param dataType the data type definition.
* @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.
*/
SingleDataField(const string name, const string comment,
const string unit, DataType* dataType, const PartType partType,
const size_t length)
: DataField(name, comment),
m_unit(unit), m_dataType(dataType), m_partType(partType),
m_length(length) {}
SingleDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length)
: DataField(name, attributes),
m_partType(partType), m_dataType(dataType), m_length(length) {}
/**
* Destructor.
@@ -282,16 +352,15 @@ class SingleDataField : public DataField {
virtual ~SingleDataField() {}
// @copydoc
SingleDataField* clone() override;
const SingleDataField* clone() const override;
/**
* 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 comment the field comment.
* @param unit the value unit.
* @param attributes the additional named attributes.
* @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 values the value=text assignments.
* @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.
* Note: the caller needs to free the created instance.
*/
static result_t create(const string id, const size_t length,
const string name, const string comment, const string unit,
const PartType partType, int divisor, map<unsigned int, string> values,
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
/**
* Get the value unit.
* @return the value unit.
*/
string getUnit() const { return m_unit; }
static result_t create(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, int divisor, map<unsigned int, string> values,
const string constantValue, const bool verifyValue, SingleDataField* &returnField);
/**
* Get whether this field is ignored.
@@ -324,13 +386,11 @@ class SingleDataField : public DataField {
PartType getPartType() const { return m_partType; }
// @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
result_t derive(string name, string comment,
string unit, const PartType partType,
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
/**
* 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
* 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
void dump(ostream& output) override;
void dump(ostream& output) const override;
// @copydoc
bool hasField(const char* fieldName, bool numeric) override;
bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc
result_t read(SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) override;
result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc
result_t read(SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) override;
result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc
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:
@@ -369,9 +429,9 @@ class SingleDataField : public DataField {
* @param outputFormat the @a OutputFormat options to use.
* @return @a RESULT_OK on success, or an error code.
*/
virtual result_t readSymbols(SymbolString& input,
const size_t offset,
ostringstream& output, OutputFormat outputFormat);
virtual result_t readSymbols(const SymbolString& input,
const size_t offset,
ostringstream& output, OutputFormat outputFormat) const;
/**
* 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.
*/
virtual result_t writeSymbols(istringstream& input,
const size_t offset,
SymbolString& output, size_t* usedLength);
/** the value unit. */
const string m_unit;
/** the data type definition. */
DataType* m_dataType;
const size_t offset,
SymbolString& output, size_t* usedLength) const;
/** the message part in which the field is stored. */
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. */
const size_t m_length;
};
@@ -407,17 +464,15 @@ class ValueListDataField : public SingleDataField {
/**
* Constructs a new instance.
* @param name the field name.
* @param comment the field comment.
* @param unit the value unit.
* @param attributes the additional named attributes.
* @param dataType the data type definition.
* @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 values the value=text assignments.
*/
ValueListDataField(const string name, const string comment,
const string unit, NumberDataType* dataType, const PartType partType,
const size_t length, const map<unsigned int, string> values)
: SingleDataField(name, comment, unit, dataType, partType, length),
ValueListDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, const map<unsigned int, string> values)
: SingleDataField(name, attributes, dataType, partType, length),
m_values(values) {}
/**
@@ -426,31 +481,29 @@ class ValueListDataField : public SingleDataField {
virtual ~ValueListDataField() {}
// @copydoc
ValueListDataField* clone() override;
const ValueListDataField* clone() const override;
// @copydoc
result_t derive(string name, string comment,
string unit, const PartType partType, int divisor,
map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
// @copydoc
void dump(ostream& output) override;
void dump(ostream& output) const override;
protected:
// @copydoc
result_t readSymbols(SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) override;
result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc
result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) override;
SymbolString& output, size_t* usedLength) const override;
private:
/** 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.
* @param name the field name.
* @param comment the field comment.
* @param unit the value unit.
* @param attributes the additional named attributes.
* @param dataType the data type definition.
* @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 value the constant value.
* @param verify whether to verify the read value against the constant value.
*/
ConstantDataField(const string name, const string comment,
const string unit, DataType* dataType, const PartType partType,
const size_t length, const string value, const bool verify)
: SingleDataField(name, comment, unit, dataType, partType, length),
ConstantDataField(const string name, const map<string, string>& attributes, const DataType* dataType,
const PartType partType, const size_t length, const string value, const bool verify)
: SingleDataField(name, attributes, dataType, partType, length),
m_value(value), m_verify(verify) {}
/**
@@ -482,26 +533,24 @@ class ConstantDataField : public SingleDataField {
virtual ~ConstantDataField() {}
// @copydoc
ConstantDataField* clone() override;
const ConstantDataField* clone() const override;
// @copydoc
result_t derive(string name, string comment,
string unit, const PartType partType, int divisor,
map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
// @copydoc
void dump(ostream& output) override;
void dump(ostream& output) const override;
protected:
// @copydoc
result_t readSymbols(SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) override;
result_t readSymbols(const SymbolString& input, const size_t offset,
ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc
result_t writeSymbols(istringstream& input, const size_t offset,
SymbolString& output, size_t* usedLength) override;
SymbolString& output, size_t* usedLength) const override;
private:
@@ -533,16 +582,13 @@ class DataFieldSet : public DataField {
/**
* Constructs a new instance.
* @param name the field name.
* @param comment the field comment.
* @param fields the @a vector of @a SingleDataField instances part of this set.
*/
DataFieldSet(const string name, const string comment,
const vector<SingleDataField*> fields)
: DataField(name, comment), m_fields(fields) {
DataFieldSet(const string name, const vector<const SingleDataField*> fields)
: DataField(name), m_fields(fields) {
bool uniqueNames = true;
map<string, string> names;
for (vector<SingleDataField*>::const_iterator it = fields.begin(); it != fields.end(); it++) {
SingleDataField* field = *it;
for (auto field : fields) {
if (field->isIgnored()) {
continue;
}
@@ -562,31 +608,29 @@ class DataFieldSet : public DataField {
virtual ~DataFieldSet();
// @copydoc
DataFieldSet* clone() override;
const DataFieldSet* clone() const override;
// @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
string getName(ssize_t fieldIndex = -1) override;
string getName(const ssize_t fieldIndex = -1) const override;
// @copydoc
result_t derive(string name, string comment,
string unit, const PartType partType,
int divisor, map<unsigned int, string> values,
vector<SingleDataField*>& fields) override;
result_t derive(const string name, map<string, string> attributes, const PartType partType,
int divisor, map<unsigned int, string> values, vector<const SingleDataField*>& fields) const override;
/**
* Returns the @a SingleDataField at the specified index.
* @param index the index of the @a SingleDataField to return.
* @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()) {
return NULL;
}
return m_fields[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(); }
// @copydoc
bool hasField(const char* fieldName, bool numeric) override;
bool hasField(const char* fieldName, bool numeric) const override;
// @copydoc
void dump(ostream& output) override;
void dump(ostream& output) const override;
// @copydoc
result_t read(SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) override;
result_t read(const SymbolString& data, size_t offset,
unsigned int& output, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc
result_t read(SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) override;
result_t read(const SymbolString& data, size_t offset,
ostringstream& output, OutputFormat outputFormat, ssize_t outputIndex = -1,
bool leadingSeparator = false, const char* fieldName = NULL, ssize_t fieldIndex = -1) const override;
// @copydoc
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:
@@ -631,7 +675,7 @@ class DataFieldSet : public DataField {
static DataFieldSet* s_identFields;
/** 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. */
bool m_uniqueNames;
@@ -674,14 +718,14 @@ class DataFieldTemplates : public MappedFileReader {
* @return @a RESULT_OK on success, or an error code.
* 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
result_t getFieldMap(vector<string>& row, string& errorDescription) override;
result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc
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.
@@ -689,12 +733,12 @@ class DataFieldTemplates : public MappedFileReader {
* @return the template @a DataField instance, or NULL.
* Note: the caller may not free the returned instance.
*/
DataField* get(string name);
const DataField* get(string name) const;
private:
/** the known template @a DataField instances by name. */
map<string, DataField*> m_fieldsByName;
map<string, const DataField*> m_fieldsByName;
};
} // 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,
const size_t length, unsigned int& value) {
result_t StringDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) const {
return RESULT_EMPTY;
}
result_t StringDataType::readSymbols(SymbolString& input,
result_t StringDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) {
ostringstream& output, OutputFormat outputFormat) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol;
@@ -116,7 +116,7 @@ result_t StringDataType::readSymbols(SymbolString& input,
result_t StringDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) {
SymbolString& output, size_t* usedLength) const {
size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1;
@@ -196,14 +196,14 @@ result_t StringDataType::writeSymbols(istringstream& input,
}
result_t DateTimeDataType::readRawValue(SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) {
result_t DateTimeDataType::readRawValue(const SymbolString& input, const size_t offset,
const size_t length, unsigned int& value) const {
return RESULT_EMPTY;
}
result_t DateTimeDataType::readSymbols(SymbolString& input,
result_t DateTimeDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) {
ostringstream& output, OutputFormat outputFormat) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol, last = 0, hour = 0;
@@ -335,7 +335,7 @@ result_t DateTimeDataType::readSymbols(SymbolString& input,
result_t DateTimeDataType::writeSymbols(istringstream& input,
size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) {
SymbolString& output, size_t* usedLength) const {
size_t start = 0, count = length;
bool remainder = count == REMAIN_LEN && hasFlag(ADJ);
int incr = 1;
@@ -527,7 +527,7 @@ bool NumberDataType::dump(ostream& output, size_t length, const bool appendSepar
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) {
divisor = 1;
}
@@ -570,19 +570,18 @@ result_t NumberDataType::derive(int divisor, size_t bitCount, NumberDataType* &d
}
if (m_bitCount < 8) {
derived = new NumberDataType(m_id, bitCount, m_flags, m_replacement,
m_firstBit, divisor);
m_firstBit, divisor, m_baseType ? m_baseType : this);
} else {
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);
return RESULT_OK;
}
result_t NumberDataType::readRawValue(SymbolString& input,
result_t NumberDataType::readRawValue(const SymbolString& input,
size_t offset, const size_t length,
unsigned int& value) {
unsigned int& value) const {
size_t start = 0, count = length;
int incr = 1;
symbol_t symbol;
@@ -629,9 +628,9 @@ result_t NumberDataType::readRawValue(SymbolString& input,
return RESULT_OK;
}
result_t NumberDataType::readSymbols(SymbolString& input,
result_t NumberDataType::readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) {
ostringstream& output, OutputFormat outputFormat) const {
unsigned int value = 0;
int signedValue;
@@ -743,7 +742,7 @@ result_t NumberDataType::readSymbols(SymbolString& input,
result_t NumberDataType::writeRawValue(unsigned int value,
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;
int incr = 1;
symbol_t symbol;
@@ -789,7 +788,7 @@ result_t NumberDataType::writeRawValue(unsigned int value,
result_t NumberDataType::writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) {
SymbolString& output, size_t* usedLength) const {
unsigned int value;
const char* str = input.str().c_str();
@@ -906,8 +905,8 @@ bool DataTypeList::s_contrib_initialized = libebus_contrib_register();
DataTypeList::DataTypeList() {
add(new StringDataType("STR", MAX_LEN*8, ADJ, ' ')); // >= 1 byte character string filled up with space
// unsigned decimal in BCD, 0000 - 9999 (fixed length)
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1));
add(new NumberDataType("UCH", 8, 0, 0xff, 0, 0xfe, 1)); // unsigned integer, 0 - 254
add(new NumberDataType("PIN", 16, FIX|BCD|REV, 0xffff, 0, 0x9999, 1, NULL));
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
// >= 1 byte character string filled up with 0x00 (null terminated string)
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));
// 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 NumberDataType("BDY", 8, DAY, 0x07, 0, 6, 1)); // 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("BCD", 8, BCD, 0xff, 0, 99, 1)); // 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", 24, BCD, 0xffffff, 0, 999999, 1)); // 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("HCD", 32, HCD|BCD|REQ, 0, 0, 99999999, 1)); // 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", 16, HCD|BCD|REQ, 0, 0, 9999, 1)); // 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("SCH", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
add(new NumberDataType("D1B", 8, SIG, 0x80, 0x81, 0x7f, 1)); // signed integer, -127 - +127
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, NULL)); // weekday, "Mon" - "Sun" (0x01 - 0x07) [Vaillant type]
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, NULL)); // unsigned decimal in BCD, 0 - 9999
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, NULL)); // unsigned decimal in BCD, 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, NULL)); // unsigned decimal in HCD, 0 - 99
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, NULL)); // unsigned decimal in HCD, 0 - 999999
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, NULL)); // signed integer, -127 - +127
// 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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("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)
@@ -1010,21 +1009,20 @@ DataTypeList* DataTypeList::getInstance() {
}
void DataTypeList::clear() {
for (list<DataType*>::iterator it = m_cleanupTypes.begin(); it != m_cleanupTypes.end(); it++) {
delete *it;
for (auto& it : m_cleanupTypes) {
delete it;
}
m_cleanupTypes.clear();
m_typesByIdLength.clear();
m_typesById.clear();
}
result_t DataTypeList::add(DataType* dataType) {
result_t DataTypeList::add(const DataType* dataType) {
if (!dataType->isAdjustableLength()) {
ostringstream str;
size_t bitCount = dataType->getBitCount();
str << dataType->getId() << LENGTH_SEPARATOR << static_cast<unsigned>(bitCount >= 8?bitCount/8:bitCount);
map<string, DataType*>::iterator it = m_typesByIdLength.find(str.str());
if (it != m_typesByIdLength.end()) {
if (m_typesByIdLength.find(str.str()) != m_typesByIdLength.end()) {
return RESULT_ERR_DUPLICATE_NAME; // duplicate key
}
m_typesByIdLength[str.str()] = dataType;
@@ -1040,20 +1038,23 @@ result_t DataTypeList::add(DataType* dataType) {
return RESULT_OK;
}
DataType* DataTypeList::get(const string id, const size_t length) {
DataType* dataType = NULL;
const DataType* DataTypeList::get(const string id, const size_t length) const {
if (length > 0) {
ostringstream str;
str << id << LENGTH_SEPARATOR << static_cast<unsigned>(length);
dataType = m_typesByIdLength[str.str()];
}
if (!dataType) {
dataType = m_typesById[id];
if (dataType && length > 0 && !dataType->isAdjustableLength()) {
return NULL;
auto it = m_typesByIdLength.find(str.str());
if (it != m_typesByIdLength.end()) {
return it->second;
}
}
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
+41 -35
View File
@@ -100,6 +100,9 @@ typedef int OutputFormat;
/** bit flag for @a OutputFormat: short format (only name and value, no indentation). */
#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. */
enum PartType {
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.
* @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,
unsigned int& value) = 0;
unsigned int& value) const = 0;
/**
* Internal method for reading the field from a @a SymbolString.
@@ -238,9 +241,9 @@ class DataType {
* @param outputFormat the @a OutputFormat options to use.
* @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,
ostringstream& output, OutputFormat outputFormat) = 0;
ostringstream& output, OutputFormat outputFormat) const = 0;
/**
* Internal method for writing the field to a @a SymbolString.
@@ -253,7 +256,7 @@ class DataType {
*/
virtual result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) = 0;
SymbolString& output, size_t* usedLength) const = 0;
protected:
@@ -295,19 +298,19 @@ class StringDataType : public DataType {
virtual ~StringDataType() {}
// @copydoc
result_t readRawValue(SymbolString& input,
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) override;
unsigned int& value) const override;
// @copydoc
result_t readSymbols(SymbolString& input,
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override;
ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override;
SymbolString& output, size_t* usedLength) const override;
private:
@@ -357,19 +360,19 @@ class DateTimeDataType : public DataType {
int16_t getResolution() const { return m_resolution; }
// @copydoc
result_t readRawValue(SymbolString& input,
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) override;
unsigned int& value) const override;
// @copydoc
result_t readSymbols(SymbolString& input,
result_t readSymbols(const SymbolString& input,
const size_t offset, const size_t length,
ostringstream& output, OutputFormat outputFormat) override;
ostringstream& output, OutputFormat outputFormat) const override;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override;
SymbolString& output, size_t* usedLength) const override;
private:
@@ -398,11 +401,13 @@ class NumberDataType : public DataType {
* @param minValue the minimum raw value.
* @param maxValue the maximum raw value.
* @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,
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),
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.
@@ -412,11 +417,12 @@ class NumberDataType : public DataType {
* @param replacement the replacement value (no replacement if zero).
* @param firstBit the offset to the first bit.
* @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,
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),
m_precision(0), m_firstBit(firstBit), m_baseType(NULL) {}
m_precision(0), m_firstBit(firstBit), m_baseType(baseType) {}
/**
* Destructor.
@@ -444,7 +450,7 @@ class NumberDataType : public DataType {
* not necessary.
* @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.
@@ -472,14 +478,14 @@ class NumberDataType : public DataType {
int16_t getFirstBit() const { return m_firstBit; }
// @copydoc
result_t readRawValue(SymbolString& input,
result_t readRawValue(const SymbolString& input,
const size_t offset, const size_t length,
unsigned int& value) override;
unsigned int& value) const override;
// @copydoc
result_t readSymbols(SymbolString& input,
result_t readSymbols(const SymbolString& input,
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.
@@ -493,12 +499,12 @@ class NumberDataType : public DataType {
*/
result_t writeRawValue(unsigned int value,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength = NULL);
SymbolString& output, size_t* usedLength = NULL) const;
// @copydoc
result_t writeSymbols(istringstream& input,
const size_t offset, const size_t length,
SymbolString& output, size_t* usedLength) override;
SymbolString& output, size_t* usedLength) const override;
private:
@@ -518,7 +524,7 @@ class NumberDataType : public DataType {
const int16_t m_firstBit;
/** 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.
* 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.
* @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.
@@ -571,30 +577,30 @@ class DataTypeList {
* @return the @a DataType instance, or NULL if not available.
* 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.
* @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.
* @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:
/** 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").
* 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. */
list<DataType*> m_cleanupTypes;
list<const DataType*> m_cleanupTypes;
/** the singleton 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,
const string filename, unsigned int& lineNo, vector<string>& row, bool verbose,
size_t* hash, size_t* size) {
result_t result;
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 (!verbose) {
ostringstream error;
@@ -134,6 +137,7 @@ bool FileReader::splitFields(istream& ifs, vector<string>& row, unsigned int& li
*size += length + 1; // normalized with trailing endl
}
if (hash) {
// TODO ensure 32 bit machine produces same result
*hash ^= (hashFunction(line) << 1) ^ (length << (7 * (lineNo % 5)));
}
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.
*/
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;
}
@@ -199,7 +199,7 @@ class MappedFileReader : public FileReader {
* @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.
*/
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.
@@ -231,14 +231,14 @@ class MappedFileReader : public FileReader {
/**
* @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 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;
}
+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,
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 vector<symbol_t> id,
DataField* data, const bool deleteData,
const DataField* data, const bool deleteData,
const size_t pollPriority,
Condition* condition)
: m_circuit(circuit), m_level(level), m_name(name), m_isWrite(isWrite),
m_isPassive(isPassive), m_comment(comment),
: AttributedItem(name, attributes), m_circuit(circuit), m_level(level), m_isWrite(isWrite),
m_isPassive(isPassive),
m_srcAddress(srcAddress), m_dstAddress(dstAddress),
m_id(id), m_data(data), m_deleteData(deleteData),
m_pollPriority(pollPriority),
m_usedByCondition(false), m_isScanMessage(false), m_condition(condition),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
m_key = createKey(id, isWrite, isPassive, srcAddress, dstAddress);
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0),
m_key(createKey(id, isWrite, isPassive, srcAddress, dstAddress)) {
if (circuit == "scan") {
setScanMessage();
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,
const symbol_t pb, const symbol_t sb,
const bool broadcast, DataField* data, const bool deleteData)
: m_circuit(circuit), m_level(level), m_name(name), m_isWrite(broadcast),
m_isPassive(false), m_comment(),
const bool broadcast, const DataField* data, const bool deleteData)
: AttributedItem(name), m_circuit(circuit), m_level(level), m_isWrite(broadcast),
m_isPassive(false),
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_usedByCondition(false), m_isScanMessage(true), m_condition(NULL),
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0) {
m_id.push_back(pb);
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;
m_lastUpdateTime(0), m_lastChangeTime(0), m_pollCount(0), m_lastPollTime(0),
m_key(createKey(pb, sb, broadcast)) {
}
@@ -214,7 +207,7 @@ Message::Message(const string circuit, const string level, const string name,
* empty and @p replaceStar is @p true.
* @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) {
if (defaults.empty()) {
return value;
@@ -222,7 +215,8 @@ string getDefault(const string value, map<string, string>& defaults, const strin
if (value.length() == 0 && replaceStar && required) {
return value;
}
string defaultStr = defaults[fieldName];
auto it = defaults.find(fieldName);
const string defaultStr = it == defaults.end() ? "" : it->second;
if (!replaceStar || defaultStr.empty()) {
return value.length() > 0 ? value : defaultStr;
}
@@ -279,6 +273,15 @@ uint64_t Message::createKey(MasterSymbolString& master, size_t maxIdLength, bool
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) {
istringstream in(input);
while (!in.eof()) {
@@ -314,8 +317,9 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
bool isWrite = false, isPassive = false;
string defaultName;
size_t pollPriority = 0;
string typeStr = row["type"];
string typeStr = pluck(row, "type");
if (typeStr.empty()) {
errorDescription = "empty type";
return RESULT_ERR_EOF;
}
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];
string circuit = getDefault(row["circuit"], defaults, "circuit", true); // [circuit[#level]]
string level = getDefault(row["level"], defaults, "level", true);
string circuit = getDefault(pluck(row, "circuit"), defaults, "circuit", true); // [circuit[#level]]
string level = getDefault(pluck(row, "level"), defaults, "level", true);
size_t pos = circuit.find('#'); // TODO remove some day
if (pos != string::npos) {
level = circuit.substr(pos+1);
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()) {
errorDescription = "name in "+MappedFileReader::combineRow(row);
errorDescription = "name";
return RESULT_ERR_MISSING_ARG; // empty name
}
string comment = getDefault(row["comment"], defaults, "comment", true); // [comment]
string str = getDefault(row["qq"], defaults, "qq"); // [QQ[;QQ]*]
string comment = getDefault(pluck(row, "comment"), defaults, "comment", true); // [comment]
if (!comment.empty()) {
row["comment"] = comment;
}
string str = getDefault(pluck(row, "qq"), defaults, "qq"); // [QQ[;QQ]*]
symbol_t srcAddress;
if (str.empty()) {
srcAddress = SYN; // no specific source
} else {
srcAddress = (symbol_t)parseInt(str.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
errorDescription = "qq "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "qq "+str;
return result;
}
if (!isMaster(srcAddress)) {
errorDescription = "qq "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "qq "+str;
return RESULT_ERR_INVALID_ADDR;
}
}
str = getDefault(row["zz"], defaults, "zz"); // [ZZ]
str = getDefault(pluck(row, "zz"), defaults, "zz"); // [ZZ]
vector<symbol_t> dstAddresses;
bool isBroadcastOrMasterDestination = false;
if (str.empty()) {
@@ -383,11 +390,11 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
FileReader::trim(token);
symbol_t dstAddress = (symbol_t)parseInt(token.c_str(), 16, 0, 0xff, result);
if (result != RESULT_OK) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row);
errorDescription = "zz "+token;
return result;
}
if (!isValidAddress(dstAddress)) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row);
errorDescription = "zz "+token;
return RESULT_ERR_INVALID_ADDR;
}
bool broadcastOrMaster = (dstAddress == BROADCAST) || isMaster(dstAddress);
@@ -395,7 +402,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
isBroadcastOrMasterDestination = broadcastOrMaster;
first = false;
} else if (isBroadcastOrMasterDestination != broadcastOrMaster) {
errorDescription = "zz "+token+" in "+MappedFileReader::combineRow(row);
errorDescription = "zz "+token;
return RESULT_ERR_INVALID_ADDR;
}
dstAddresses.push_back(dstAddress);
@@ -403,21 +410,21 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
}
vector<symbol_t> id;
str = row["pbsb"]; // [PBSB]
str = pluck(row, "pbsb"); // [PBSB]
bool useDefaults = str.empty();
if (useDefaults) {
str = getDefault(str, defaults, "pbsb");
}
result = parseId(str, id);
if (result != RESULT_OK) {
errorDescription = "pbsb "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "pbsb "+str;
return result;
}
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
}
str = row["id"]; // [ID] (optional master data)
str = pluck(row, "id"); // [ID] (optional master data)
string defaultIdPrefix;
if (useDefaults) {
defaultIdPrefix = getDefault("", defaults, "id");
@@ -437,7 +444,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
if (lastChainLengthSpecified) {
chainLength = parseInt(str.substr(lengthPos+1).c_str(), 10, 0, MAX_POS, result);
if (result != RESULT_OK) {
errorDescription = "id "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "id "+str;
return result;
}
str.resize(lengthPos);
@@ -445,11 +452,11 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
vector<symbol_t> chainId = id;
result = parseId(str, chainId);
if (result != RESULT_OK) {
errorDescription = "id "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "id "+str;
return result;
}
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;
}
chainIds.push_back(chainId);
@@ -467,7 +474,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
}
}
if (maxLength+chainLength > 255) {
errorDescription = "id length "+str+" in "+MappedFileReader::combineRow(row);
errorDescription = "id length "+str;
return RESULT_ERR_INVALID_POS;
}
maxLength += chainLength;
@@ -476,7 +483,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
id = chainIds.front();
if (chainIds.size() > 1) {
if (isPassive) {
errorDescription = "id (passive) in "+MappedFileReader::combineRow(row);
errorDescription = "id (passive)";
return RESULT_ERR_INVALID_LIST;
}
if (id.size() > chainPrefixLength) {
@@ -493,10 +500,10 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
if (!subDefaults.empty()) {
subRows.insert(subRows.begin(), subDefaults.begin(), subDefaults.end());
}
DataField* data = NULL;
const DataField* data = NULL;
if (subRows.empty()) {
vector<SingleDataField*> fields;
data = new DataFieldSet("", "", fields);
vector<const SingleDataField*> fields;
data = new DataFieldSet("", fields);
} else {
result = DataField::create(subRows, errorDescription, templates, data, isWrite, false,
isBroadcastOrMasterDestination, maxLength);
@@ -508,7 +515,7 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
|| data->getLength(pt_slaveData, maxLength) > maxLength) {
// max NN exceeded
delete data;
errorDescription = "data length in "+MappedFileReader::combineRow(row);
errorDescription = "data length";
return RESULT_ERR_INVALID_POS;
}
unsigned int index = 0;
@@ -523,10 +530,10 @@ result_t Message::create(map<string, string> row, vector< map<string, string> >
}
Message* message;
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);
} 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);
}
messages.push_back(message);
@@ -561,9 +568,9 @@ bool Message::extractFieldIds(string str, vector<size_t>& fields, bool checkAbbr
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,
m_isWrite, m_isPassive, m_comment,
m_isWrite, m_isPassive, m_attributes,
srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_data, false,
m_pollPriority, m_condition);
@@ -573,7 +580,7 @@ Message* Message::derive(const symbol_t dstAddress, const symbol_t srcAddress, c
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) {
ostringstream out;
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;
}
bool Message::checkIdPrefix(vector<symbol_t>& id) {
bool Message::checkIdPrefix(const vector<symbol_t>& id) const {
if (id.size() > m_id.size()) {
return false;
}
@@ -616,7 +624,7 @@ bool Message::checkIdPrefix(vector<symbol_t>& id) {
return true;
}
bool Message::checkId(MasterSymbolString& master, size_t* index) {
bool Message::checkId(const MasterSymbolString& master, size_t* index) const {
size_t idLen = getIdLength();
if (master.getDataSize() < idLen) {
return false;
@@ -632,7 +640,7 @@ bool Message::checkId(MasterSymbolString& master, size_t* index) {
return true;
}
bool Message::checkId(Message& other) {
bool Message::checkId(Message& other) const {
size_t idLen = getIdLength();
if (idLen != other.getIdLength() || getCount() > 1) { // only equal for non-chained messages
return false;
@@ -640,7 +648,7 @@ bool Message::checkId(Message& other) {
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);
}
@@ -670,7 +678,7 @@ bool Message::isAvailable() {
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);
}
@@ -749,8 +757,8 @@ result_t Message::storeLastData(MasterSymbolString& master, SlaveSymbolString& s
}
result_t Message::storeLastData(MasterSymbolString& data, size_t index) {
if (data.size() > 0
&& (m_isWrite || this->m_dstAddress == BROADCAST || isMaster(this->m_dstAddress))) {
if (data.size() > 0 && (m_isWrite || this->m_dstAddress == BROADCAST || isMaster(this->m_dstAddress)
|| data.getDataSize() + 2 > m_id.size())) {
time(&m_lastUpdateTime);
}
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
m_lastMasterData = data;
break;
// else: identical
}
return RESULT_OK;
}
@@ -772,12 +781,13 @@ result_t Message::storeLastData(SlaveSymbolString& data, size_t index) {
if (data != m_lastSlaveData) {
m_lastChangeTime = m_lastUpdateTime;
m_lastSlaveData = data;
const SlaveSymbolString& chk = getLastSlaveData();
}
return RESULT_OK;
}
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;
result_t result = m_data->read(m_lastMasterData, offset,
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,
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,
output, outputFormat, -1, leadingSeparator, fieldName, fieldIndex);
if (result < RESULT_OK) {
@@ -804,7 +814,7 @@ result_t Message::decodeLastSlaveData(ostringstream& output, OutputFormat output
}
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();
result_t result = m_data->read(m_lastMasterData, getIdLength(), output, outputFormat, -1,
leadingSeparator, fieldName, fieldIndex);
@@ -825,7 +835,7 @@ result_t Message::decodeLastData(ostringstream& output, OutputFormat outputForma
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);
if (result < RESULT_OK) {
return result;
@@ -842,7 +852,7 @@ result_t Message::decodeLastDataNumField(unsigned int& output, const char* field
return result;
}
bool Message::isLessPollWeight(const Message* other) {
bool Message::isLessPollWeight(const Message* other) const {
size_t tprio = m_pollPriority;
size_t oprio = other->m_pollPriority;
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;
if (fieldIds == NULL) {
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) {
case MESSAGEFIELD_TYPE:
if (withConditions && m_condition != NULL) {
@@ -956,16 +966,16 @@ void Message::dumpField(ostream& output, size_t fieldId, bool withConditions) {
}
break;
case MESSAGEFIELD_CIRCUIT:
DataField::dumpString(output, m_circuit, false);
dumpString(output, m_circuit, false);
break;
case MESSAGEFIELD_LEVEL:
DataField::dumpString(output, m_level, false);
dumpString(output, m_level, false);
break;
case MESSAGEFIELD_NAME:
DataField::dumpString(output, m_name, false);
dumpString(output, m_name, false);
break;
case MESSAGEFIELD_COMMENT:
DataField::dumpString(output, m_comment, false);
dumpAttribute(output, "comment", false);
break;
case MESSAGEFIELD_QQ:
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,
const bool isWrite, const string comment,
const bool isWrite, const map<string, string>& attributes,
const symbol_t srcAddress, const symbol_t dstAddress,
const vector<symbol_t> id,
vector< vector<symbol_t> > ids, vector<size_t> lengths,
DataField* data, const bool deleteData,
const DataField* data, const bool deleteData,
const size_t pollPriority,
Condition* condition)
: Message(circuit, level, name, isWrite, false, comment,
: Message(circuit, level, name, isWrite, false, attributes,
srcAddress, dstAddress, id,
data, deleteData, pollPriority, condition),
m_ids(ids), m_lengths(lengths),
@@ -1033,9 +1043,9 @@ ChainedMessage::~ChainedMessage() {
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,
m_isWrite, m_comment,
m_isWrite, m_attributes,
srcAddress == SYN ? m_srcAddress : srcAddress, dstAddress,
m_id, m_ids, m_lengths, m_data, false,
m_pollPriority, m_condition);
@@ -1045,7 +1055,7 @@ Message* ChainedMessage::derive(const symbol_t dstAddress, const symbol_t srcAdd
return result;
}
bool ChainedMessage::checkId(MasterSymbolString& master, size_t* index) {
bool ChainedMessage::checkId(const MasterSymbolString& master, size_t* index) const {
size_t idLen = getIdLength();
if (master.getDataSize() < idLen) {
return false;
@@ -1076,7 +1086,7 @@ bool ChainedMessage::checkId(MasterSymbolString& master, size_t* index) {
return false;
}
bool ChainedMessage::checkId(Message& other) {
bool ChainedMessage::checkId(Message& other) const {
size_t idLen = getIdLength();
if (idLen != other.getIdLength() || other.getCount() == 1) { // only equal for chained messages
return false;
@@ -1242,7 +1252,7 @@ result_t ChainedMessage::combineLastParts() {
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) {
Message::dumpField(output, fieldId, withConditions);
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
* 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) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++) {
Message* message = *msgIt;
for (auto message : messages) {
if (sameIdExtAs && !message->checkId(*sameIdExtAs)) {
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
* 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) {
for (vector<Message*>::iterator msgIt = messages.begin(); msgIt != messages.end(); msgIt++) {
Message* message = *msgIt;
for (auto message : messages) {
if (sameIdExtAs && !message->checkId(*sameIdExtAs)) {
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,
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 level;
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"];
}
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);
return RESULT_OK;
}
@@ -1438,7 +1449,7 @@ result_t Condition::create(const string condName, map<string, string> row, map<s
return RESULT_OK;
}
SimpleCondition* SimpleCondition::derive(string valueList) {
SimpleCondition* SimpleCondition::derive(string valueList) const {
if (valueList.empty()) {
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);
}
void SimpleCondition::dump(ostream& output, bool matched) {
void SimpleCondition::dump(ostream& output, bool matched) const {
if (matched) {
if (!m_isTrue) {
return;
@@ -1518,7 +1529,7 @@ result_t SimpleCondition::resolve(MessageMap* messages, ostringstream& errorMess
}
// clone the message with dedicated dstAddress if necessary
uint64_t key = message->getDerivedKey(m_dstAddress);
vector<Message*>* derived = messages->getByKey(key);
const vector<Message*>* derived = messages->getByKey(key);
if (derived == NULL) {
message = message->derive(m_dstAddress, true);
messages->add(message);
@@ -1600,17 +1611,15 @@ bool SimpleStringCondition::checkValue(Message* message, string field) {
}
void CombinedCondition::dump(ostream& output, bool matched) {
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
Condition* condition = *it;
void CombinedCondition::dump(ostream& output, bool matched) const {
for (auto condition : m_conditions) {
condition->dump(output, matched);
}
}
result_t CombinedCondition::resolve(MessageMap* messages, ostringstream& errorMessage,
void (*readMessageFunc)(Message* message)) {
for (vector<Condition*>::iterator it = m_conditions.begin(); it != m_conditions.end(); it++) {
Condition* condition = *it;
for (auto condition : m_conditions) {
ostringstream dummy;
result_t ret = condition->resolve(messages, dummy, readMessageFunc);
if (ret != RESULT_OK) {
@@ -1662,23 +1671,28 @@ result_t Instruction::create(const string& contextPath, const string type,
return RESULT_ERR_INVALID_ARG;
}
string Instruction::getDestination() {
string Instruction::getDestination() const {
// ZZ.circuit[.suffix]
string ret;
if (!m_defaults["zz"].empty()) {
ret = m_defaults["zz"];
auto it = m_defaults.find("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()) {
ret += ".";
}
if (m_defaults["circuit"].empty()) {
if (circuit.empty()) {
ret += "*";
} else {
ret += m_defaults["circuit"];
ret += circuit;
}
if (!m_defaults["suffix"].empty()) {
ret += m_defaults["suffix"];
if (!suffix.empty()) {
ret += suffix;
}
}
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) {
uint64_t key = message->getKey();
bool conditional = message->isConditional();
@@ -1763,7 +1779,6 @@ result_t MessageMap::add(Message* message, bool storeByName) {
}
}
m_messagesByName[nameKey].push_back(message);
nameKey = string(isPassive ? "-P" : (isWrite ? "-W" : "-R")) + name; // also store without circuit
map<string, vector<Message*> >::iterator nameIt = m_messagesByName.find(nameKey);
if (nameIt == m_messagesByName.end()) {
@@ -1800,7 +1815,7 @@ result_t MessageMap::add(Message* message, bool storeByName) {
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,
// unit,comment
// minimum: type,name,PBSB,field,datatype
@@ -1826,55 +1841,56 @@ result_t MessageMap::getFieldMap(vector<string>& row, string& errorDescription)
bool inDataFields = false;
map<string, string> seen;
for (auto &name : row) {
tolower(name);
size_t fieldId;
string useName = name;
tolower(useName);
if (inDataFields) {
fieldId = getDataFieldId(name);
if (fieldId == UINT_MAX) {
errorDescription = "unknown field " + name;
return RESULT_ERR_INVALID_ARG;
}
if (seen.find(name) != seen.end()) {
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
return RESULT_ERR_EOF; // require at least name and type
size_t fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
useName = getDataFieldName(fieldId);
if (seen.find(useName) != seen.end()) {
if (seen.find("name") == seen.end() || seen.find("type") == seen.end()) {
errorDescription = "missing field name/type as of already seen "+useName;
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 {
fieldId = getMessageFieldId(name);
if (fieldId == UINT_MAX) {
fieldId = getDataFieldId(name);
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);
size_t fieldId = getMessageFieldId(useName);
if (fieldId != UINT_MAX && (fieldId != MESSAGEFIELD_NAME || seen.find("name") == seen.end())) {
useName = getMessageFieldName(fieldId);
} else {
if (seen.find(name) != seen.end()) {
errorDescription = "duplicate field " + name;
return RESULT_ERR_INVALID_ARG;
fieldId = getDataFieldId(useName);
if (fieldId != UINT_MAX) {
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 (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
}
} else {
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
}
} else 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_OK;
}
@@ -1884,9 +1900,13 @@ result_t MessageMap::addDefaultFromFile(map<string, string>& row, vector< map<st
// check for condition in defaults
string type = row["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] == ']') {
// condition
map<string, string> defaults = getDefaults()[""];
type = type.substr(1, type.length()-2);
if (type.find('[') != string::npos || type.find(']') != string::npos) {
errorDescription = "invalid condition name "+type;
@@ -1907,41 +1927,40 @@ result_t MessageMap::addDefaultFromFile(map<string, string>& row, vector< map<st
m_conditions[key] = condition;
return RESULT_OK;
}
if (!type.empty()) {
map<string, string> defaults = getDefaults()[""];
string defaultCircuit = defaults["circuit"];
string defaultSuffix = defaults["suffix"];
defaults.erase("suffix");
for (auto entry : row) {
string value = entry.second;
if (entry.first == "circuit" && !defaultCircuit.empty()) { // TODO remove some day
if (value.empty()) {
value = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
} else if (value[0] == '#') {
// move access level behind default circuit and suffix: "circuit[.suffix]#level"
value = defaultCircuit+defaultSuffix+value;
} else if (!defaultSuffix.empty() && value.find_last_of('.') == string::npos) {
// circuit suffix not yet present
size_t pos = value.find_first_of('#');
if (pos == string::npos) {
value += defaultSuffix; // append default suffix: "circuit.suffix"
} else {
// insert default suffix: "circuit.suffix#level"
value = value.substr(0, pos)+defaultSuffix+value.substr(pos);
}
if (type.empty()) {
errorDescription = "invalid default definition";
return RESULT_ERR_INVALID_ARG;
}
string defaultCircuit = defaults["circuit"];
string defaultSuffix = defaults["suffix"];
defaults.erase("suffix");
for (auto entry : row) {
string value = entry.second;
if (entry.first == "circuit" && !defaultCircuit.empty()) { // TODO remove some day
if (value.empty()) {
value = defaultCircuit+defaultSuffix; // set default circuit and suffix: "circuit[.suffix]"
} else if (value[0] == '#') {
// move access level behind default circuit and suffix: "circuit[.suffix]#level"
value = defaultCircuit+defaultSuffix+value;
} else if (!defaultSuffix.empty() && value.find_last_of('.') == string::npos) {
// circuit suffix not yet present
size_t pos = value.find_first_of('#');
if (pos == string::npos) {
value += defaultSuffix; // append default suffix: "circuit.suffix"
} 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;
vector< map<string, string> > subDefaults = subRows; // ensure to have a copy
getSubDefaults()[type] = subDefaults;
return RESULT_OK;
if (!value.empty() || defaults[entry.first].empty()) {
defaults[entry.first] = value;
}
}
errorDescription = "invalid default definition";
return RESULT_ERR_INVALID_ARG;
getDefaults()[type] = defaults;
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,
@@ -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) {
// check if combined or simple condition is already known
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()) {
condition = it->second;
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,
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) {
symbol_t* destAddress, unsigned int* software, unsigned int* hardware) const {
string ident, circuit, suffix;
unsigned int sw = UINT_MAX, hw = UINT_MAX;
string remain = filename;
@@ -2180,7 +2199,7 @@ Message* MessageMap::getScanMessage(const symbol_t dstAddress) {
return NULL;
}
uint64_t key = m_scanMessage->getDerivedKey(dstAddress);
vector<Message*>* msgs = getByKey(key);
const vector<Message*>* msgs = getByKey(key);
if (msgs != NULL) {
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 overallResult = RESULT_OK;
vector<string> remove;
for (map<string, vector<Instruction*> >::iterator it = m_instructions.begin(); it != m_instructions.end(); it++) {
vector<Instruction*> instructions = it->second;
for (auto& it : m_instructions) {
auto& instructions = it.second;
bool removeSingletons = false;
vector<Instruction*> remain;
for (vector<Instruction*>::iterator lit = instructions.begin(); lit != instructions.end(); lit++) {
Instruction* instruction = *lit;
for (auto instruction : instructions) {
if (removeSingletons && instruction->isSingleton()) {
delete instruction;
continue;
@@ -2238,6 +2256,11 @@ result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageF
instruction->isSingleton()?readMessageFunc:NULL);
if (result != RESULT_OK) {
overallResult = result;
log << "error resolving condition for \"" << instruction->getDestination() << "\": "
<< getResultCode(result);
if (!errorDescription.empty()) {
log << " " << errorDescription;
}
} else if (condition->isTrue()) {
execute = true;
}
@@ -2268,13 +2291,13 @@ result_t MessageMap::executeInstructions(ostringstream& log, void (*readMessageF
}
}
if (remain.empty()) {
remove.push_back(it->first);
remove.push_back(it.first);
} else {
it->second = remain;
it.second = remain;
}
}
for (vector<string>::iterator it = remove.begin(); it != remove.end(); it++) {
m_instructions.erase(*it);
for (auto it : remove) {
m_instructions.erase(it);
}
return overallResult;
}
@@ -2289,11 +2312,15 @@ void MessageMap::addLoadedFile(symbol_t address, string file, string comment) {
}
}
vector<string>& MessageMap::getLoadedFiles(symbol_t address) {
return m_loadedFiles[address];
const vector<string>& MessageMap::getLoadedFiles(symbol_t address) const {
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;
for (auto& loadedFile : m_loadedFileInfos) {
ret.push_back(loadedFile.first);
@@ -2301,8 +2328,8 @@ vector<string> MessageMap::getLoadedFiles() {
return ret;
}
bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* hash, size_t* size, time_t* time) {
map<string, LoadedFileInfo>::iterator it = m_loadedFileInfos.find(filename);
bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* hash, size_t* size, time_t* time) const {
auto it = m_loadedFileInfos.find(filename);
if (it == m_loadedFileInfos.end()) {
comment = "";
hash = size = 0;
@@ -2322,8 +2349,8 @@ bool MessageMap::getLoadedFileInfo(string filename, string& comment, size_t* has
return true;
}
vector<Message*>* MessageMap::getByKey(const uint64_t key) {
map<uint64_t, vector<Message*> >::iterator it = m_messagesByKey.find(key);
const vector<Message*>* MessageMap::getByKey(const uint64_t key) const {
auto it = m_messagesByKey.find(key);
if (it != m_messagesByKey.end()) {
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,
const bool isPassive) {
const bool isPassive) const {
string lcircuit = circuit;
FileReader::tolower(lcircuit);
string lname = name;
@@ -2345,7 +2372,7 @@ Message* MessageMap::find(const string& circuit, const string& name, const strin
} else {
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()) {
Message* message = getFirstAvailable(it->second);
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,
const bool completeMatch, const bool withRead, const bool withWrite, const bool withPassive,
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;
string lcircuit = circuit;
FileReader::tolower(lcircuit);
@@ -2368,12 +2395,11 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
bool checkCircuit = lcircuit.length() > 0;
bool checkLevel = levels != "*";
bool checkName = lname.length() > 0;
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
if (it->first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-"
for (auto it : m_messagesByName) {
if (it.first[0] == '-') { // avoid duplicates: instances stored multiple times have a key starting with "-"
continue;
}
for (vector<Message*>::iterator msgIt = it->second.begin(); msgIt != it->second.end(); msgIt++) {
Message* message = *msgIt;
for (auto message : it.second) {
if (checkLevel && !message->hasLevel(levels, includeEmptyLevel)) {
continue;
}
@@ -2415,7 +2441,7 @@ deque<Message*> MessageMap::findAll(const string& circuit, const string& name, c
}
}
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,
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) {
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) {
it = m_messagesByKey.find(key);
if (it != m_messagesByKey.end()) {
@@ -2596,17 +2622,16 @@ Message* MessageMap::getNextPoll() {
return ret;
}
void MessageMap::dump(ostream& output, bool withConditions) {
void MessageMap::dump(ostream& output, bool withConditions) const {
bool first = true;
Message::dumpHeader(output, NULL);
output << endl;
for (map<string, vector<Message*> >::iterator it = m_messagesByName.begin(); it != m_messagesByName.end(); it++) {
if (it->first[0] == '-') { // skip instances stored multiple times (key starting with "-")
for (auto it : m_messagesByName) {
if (it.first[0] == '-') { // skip instances stored multiple times (key starting with "-")
continue;
}
if (m_addAll) {
for (vector<Message*>::iterator mit = it->second.begin(); mit != it->second.end(); mit++) {
Message* message = *mit;
for (auto message : it.second) {
if (!message) {
continue;
}
@@ -2618,7 +2643,7 @@ void MessageMap::dump(ostream& output, bool withConditions) {
message->dump(output, NULL, withConditions);
}
} else {
Message* message = getFirstAvailable(it->second);
Message* message = getFirstAvailable(it.second);
if (!message) {
continue;
}
+82 -96
View File
@@ -108,7 +108,7 @@ class MessageMap;
/**
* Defines parameters of a message sent or received on the bus.
*/
class Message {
class Message : public AttributedItem {
friend class MessageMap;
public:
/**
@@ -119,7 +119,7 @@ class Message {
* @param isWrite whether this is a write message.
* @param isPassive true if message can only be initiated by a participant other than us,
* 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 dstAddress the destination address, or @a SYN for any (set later).
* @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.
*/
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 vector<symbol_t> id,
DataField* data, const bool deleteData,
const DataField* data, const bool deleteData,
const size_t pollPriority = 0,
Condition* condition = NULL);
@@ -151,7 +151,7 @@ class Message {
*/
Message(const string circuit, const string level, const string name,
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:
@@ -184,6 +184,15 @@ class Message {
static uint64_t createKey(MasterSymbolString& master,
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.
* @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.
*/
bool isScanMessage() { return m_isScanMessage; }
bool isScanMessage() const { return m_isScanMessage; }
/**
* Derive a new @a Message from this message.
@@ -253,7 +262,7 @@ class Message {
* @return the derived @a Message instance.
*/
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.
@@ -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.
* @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.
@@ -282,7 +291,7 @@ class Message {
* level to check.
* @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);
}
@@ -294,18 +303,12 @@ class Message {
*/
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.
* @param fieldIndex the index of the field.
* @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.
@@ -320,12 +323,6 @@ class Message {
*/
bool isPassive() const { return m_isPassive; }
/**
* Get the comment.
* @return the comment.
*/
string getComment() const { return m_comment; }
/**
* Get the source address.
* @return the source address, or @a SYN for any.
@@ -361,7 +358,7 @@ class Message {
* @param id the ID bytes to check against.
* @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.
@@ -369,27 +366,27 @@ class Message {
* @param index the variable in which to store the message part index, or NULL to ignore.
* @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.
* @param other the other @a Message to check against.
* @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.
*/
uint64_t getKey() { return m_key; }
uint64_t getKey() const { return m_key; }
/**
* Return the derived key for storing in @a MessageMap.
* @param dstAddress the destination address for the derivation.
* @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.
@@ -427,12 +424,12 @@ class Message {
* @param numeric true for a numeric field, false for a string field.
* @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.
*/
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.
@@ -505,7 +502,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code.
*/
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.
@@ -517,7 +514,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code.
*/
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.
@@ -529,7 +526,7 @@ class Message {
* @return @a RESULT_OK on success, or an error code.
*/
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.
@@ -538,44 +535,44 @@ class Message {
* @param fieldIndex the optional index of the named field, or -1.
* @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.
* @return the last seen @a MasterSymbolString.
*/
MasterSymbolString& getLastMasterData() { return m_lastMasterData; }
const MasterSymbolString& getLastMasterData() const { return m_lastMasterData; }
/**
* Get the last seen slave data.
* @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.
* @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.
* @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.
* @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.
* @param other the other @a Message to compare with.
* @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.
@@ -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 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.
@@ -598,7 +595,7 @@ class Message {
* @param fieldId the field ID to write (see @p MESSAGEFIELD_TYPE constants).
* @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:
@@ -608,9 +605,6 @@ class Message {
/** the optional access 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. */
const bool m_isWrite;
@@ -618,8 +612,8 @@ class Message {
* false if message can be initiated by any participant. */
const bool m_isPassive;
/** the comment. */
const string m_comment;
/** the additional named attributes. */
const map<string, string> m_attributes;
/** the source address, or @a SYN for any (only relevant if passive). */
const symbol_t m_srcAddress;
@@ -628,7 +622,7 @@ class Message {
const symbol_t m_dstAddress;
/** 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.
@@ -651,10 +645,10 @@ class Message {
* <li>bytes 3-0: ID bytes (with cyclic xor if more than 4)</li>
* </ul>
*/
uint64_t m_key;
const uint64_t m_key;
/** the @a DataField for encoding/decoding the message. */
DataField* m_data;
const DataField* m_data;
/** whether to delete the @a DataField during destruction. */
const bool m_deleteData;
@@ -702,7 +696,7 @@ class ChainedMessage : public Message {
* @param level the optional access level.
* @param name the message name (unique within the same circuit and type).
* @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 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.
@@ -714,11 +708,11 @@ class ChainedMessage : public Message {
* @param condition the @a Condition for this message, or NULL.
*/
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 vector<symbol_t> id,
vector< vector<symbol_t> > ids, vector<size_t> lengths,
DataField* data, const bool deleteData,
const DataField* data, const bool deleteData,
const size_t pollPriority,
Condition* condition = NULL);
@@ -726,19 +720,19 @@ class ChainedMessage : public Message {
// @copydoc
Message* derive(const symbol_t dstAddress, const symbol_t srcAddress = SYN,
const string circuit = "") override;
const string circuit = "") const override;
// @copydoc
size_t getIdLength() const override { return m_ids[0].size() - 2; }
// @copydoc
bool checkId(MasterSymbolString& master, size_t* index = NULL) override;
bool checkId(const MasterSymbolString& master, size_t* index = NULL) const override;
// @copydoc
bool checkId(Message& other) override;
bool checkId(Message& other) const override;
// @copydoc
size_t getCount() override { return m_ids.size(); }
size_t getCount() const override { return m_ids.size(); }
protected:
@@ -765,7 +759,7 @@ class ChainedMessage : public Message {
protected:
// @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:
@@ -860,14 +854,14 @@ class Condition {
* @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.
*/
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.
* @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.
*/
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.
@@ -931,10 +925,10 @@ class SimpleCondition : public Condition {
virtual ~SimpleCondition() {}
// @copydoc
SimpleCondition* derive(string valueList) override;
SimpleCondition* derive(string valueList) const override;
// @copydoc
void dump(ostream& output, bool matched = false) override;
void dump(ostream& output, bool matched = false) const override;
// @copydoc
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.
*/
virtual bool isNumeric() { return true; }
virtual bool isNumeric() const { return true; }
protected:
@@ -1062,7 +1056,7 @@ class SimpleStringCondition : public SimpleCondition {
virtual ~SimpleStringCondition() {}
// @copydoc
bool isNumeric() override { return false; }
bool isNumeric() const override { return false; }
protected:
@@ -1093,7 +1087,7 @@ class CombinedCondition : public Condition {
virtual ~CombinedCondition() {}
// @copydoc
void dump(ostream& output, bool matched = false) override;
void dump(ostream& output, bool matched = false) const override;
// @copydoc
CombinedCondition* combineAnd(Condition* other) override { m_conditions.push_back(other); return this; }
@@ -1124,7 +1118,7 @@ class Instruction {
* executed for the same source file.
* @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) { }
/**
@@ -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
* 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.
*/
string getDestination();
string getDestination() const;
/**
* 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
* same source file. */
bool m_singleton;
const bool m_singleton;
protected:
@@ -1227,17 +1221,6 @@ class LoadInstruction : public Instruction {
*/
class LoadedFileInfo {
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. */
string m_comment;
@@ -1293,7 +1276,7 @@ class MessageMap : public MappedFileReader {
result_t add(Message* message, bool storeByName = true);
// @copydoc
result_t getFieldMap(vector<string>& row, string& errorDescription) override;
result_t getFieldMap(vector<string>& row, string& errorDescription) const override;
// @copydoc
result_t addDefaultFromFile(map<string, string>& row, vector< map<string, string> >& subRows,
@@ -1311,7 +1294,7 @@ class MessageMap : public MappedFileReader {
// @copydoc
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
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.
*/
bool hasAdditionalScanMessages() { return m_additionalScanMessages; }
bool hasAdditionalScanMessages() const { return m_additionalScanMessages; }
/**
* Resolve all @a Condition instances.
@@ -1374,13 +1357,13 @@ class MessageMap : public MappedFileReader {
* @param address the slave address.
* @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.
* @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.
@@ -1392,7 +1375,7 @@ class MessageMap : public MappedFileReader {
* @return true if the file info was found, false otherwise.
*/
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.
@@ -1400,7 +1383,7 @@ class MessageMap : public MappedFileReader {
* @return the found @a Message instances, or NULL.
* 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.
@@ -1413,7 +1396,7 @@ class MessageMap : public MappedFileReader {
* Note: the caller may not free the returned instance.
*/
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.
@@ -1439,7 +1422,7 @@ class MessageMap : public MappedFileReader {
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 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.
@@ -1454,7 +1437,7 @@ class MessageMap : public MappedFileReader {
* Note: the caller may not free the returned instance.
*/
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.
@@ -1478,25 +1461,25 @@ class MessageMap : public MappedFileReader {
* Get 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.
* @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.
* @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.
* @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.
@@ -1509,23 +1492,26 @@ class MessageMap : public MappedFileReader {
* Get 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.
* @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.
* @param output the @a ostream to append the formatted messages to.
* @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:
/** empty vector for @a getLoadedFiles(). */
static vector<string> s_noFiles;
/** whether to add all messages, even if duplicate. */
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;
}
const string SymbolString::getStr(size_t skipFirstSymbols) {
const string SymbolString::getStr(size_t skipFirstSymbols) const {
ostringstream sstr;
for (size_t i = 0; i < m_data.size(); i++) {
if (skipFirstSymbols > 0) {
+14 -1
View File
@@ -156,7 +156,7 @@ class SymbolString {
* @param skipFirstSymbols the number of first symbols to skip.
* @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.
@@ -245,6 +245,19 @@ class SymbolString {
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).
* @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)
: MappedFileReader::MappedFileReader(true), m_templates(templates), m_isSet(isSet), m_isMasterDest(isMasterDest),
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()) {
row.push_back("*name");
row.push_back("part");
@@ -84,7 +84,7 @@ class TestReader : public MappedFileReader {
const bool m_isSet;
const bool m_isMasterDest;
public:
DataField* m_fields;
const DataField* m_fields;
};
@@ -509,7 +509,7 @@ int main() {
string errorDescription;
vector<string> 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++) {
string check[5] = checks[i];
istringstream isstr(check[0]);
+1 -1
View File
@@ -82,7 +82,7 @@ class NoopReader : public FileReader {
class TestReader : public MappedFileReader {
public:
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) {
cout << "get field map: split OK" << endl;
return RESULT_OK;