added output of used-defined attributes, use const where appropriate, enhanced http global node, added base class AttributedItem
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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}";
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+199
-155
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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] == '/'))) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user