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